管理Fragment(2)

前言:这篇依然没有前言……

相关文章:

1、《Fragment详解之一——概述》2、《Fragment详解之二——基本使用方法》3、《Fragment详解之三——管理Fragment(1)》4、《Fragment详解之四——管理Fragment(2)》5、《Fragment详解之五——Fragment间参数传递》6、《Fragment详解之六——如何监听fragment中的回退事件与怎样保存fragment状态》

上一篇,给大家讲了有关Fragment管理的几个函数,即add,replace,remove,这节再讲讲其它函数,然后再给大家看一个系统BUG。

一、hide()、show()1、基本使用

这两个函数的功能非常简单,

public FragmentTransaction hide(Fragment fragment);//将指定的fragment隐藏不显示 public FragmentTransaction show(Fragment fragment);//将以前hide()过的fragment显示出来 先看下面的效果图:

代码如下:(1)、同样是新建三个fragment,命名为Fragment1,Fragment2,Fragment3,同样是用背景色和文字来区别;(2)、然后是点击“add frag1”按钮的代码

Fragment1 fragment1 = new Fragment1();addFragment(fragment1, "fragment1");其中:private void addFragment(Fragment fragment, String tag) {FragmentManager manager = getSupportFragmentManager();FragmentTransaction transaction = manager.beginTransaction();transaction.add(R.id.fragment_container,fragment, tag);transaction.addToBackStack(tag);transaction.commit();}这个函数已经在前面几章用过N多次了,就不再讲了。(3)、frag3 hide的代码:FragmentManager manager = getSupportFragmentManager();Fragment fragment = manager.findFragmentByTag("fragment3");FragmentTransaction transaction = manager.beginTransaction();transaction.hide(fragment);transaction.addToBackStack("hide fragment3");transaction.commit();也没什么难度,跟前面几篇不一样的地方就是调用了transaction.hide(fragment);函数;(4)、frag3 show的代码:FragmentManager manager = getSupportFragmentManager();Fragment fragment = manager.findFragmentByTag("fragment3");FragmentTransaction transaction = manager.beginTransaction();transaction.show(fragment);transaction.addToBackStack("show fragment3");transaction.commit();这里也基本上与以前的操作代码都一样,只是使用了transaction.show(fragment);函数2、在实战中的运用方法

如果我们使用replace来切换页面,那么在每次切换的时候,Fragment都会重新实例化,重新加载一边数据,这样非常消耗性能和用户的数据流量。这是因为replace操作,每次都会把container中的现有的fragment实例清空,然后再把指定的fragment添加进去,就就造成了在切换到以前的fragment时,就会重新实例会fragment。正确的切换方式是add(),切换时hide(),add()另一个Fragment;再次切换时,只需hide()当前,show()另一个。这样就能做到多个Fragment切换不重新实例化:(基本算法如下)

public void switchContent(Fragment from, Fragment to) {if (!to.isAdded()) { // 先判断是否被add过transaction.hide(from).add(R.id.content_frame, to).commit(); // 隐藏当前的fragment,add下一个到Activity中} else {transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个}}大家可能觉得这里有个问题,如果我们要show()的fragment不在最顶层怎么办?如果不在ADD队列的队首,那显然show()之后是不可见的;那岂不影响了APP逻辑。大家有这个想法是很棒的,但在APP中不存在这样的情况,因为我们的APP的fragment是一层层ADD进去的,而且我们的fragment实例都是唯一的,用TAG来标识,当退出的时候也是一层层剥离的,所以当用户的动作导致要添加某个fragment时,那说明这个fragment肯定是在栈顶的。二、detach()、attach()

这两个函数的声明如下:

public FragmentTransaction detach(Fragment fragment);public abstract FragmentTransaction attach(Fragment fragment);detach():会将view与fragment分离,将此将view从viewtree中删除!而且将fragment从Activity的ADD队列中移除!所以在使用detach()后,使用fragment::isAdded()返回的值是false;但此fragment实例并不会删除,此fragment的状态依然保持着使用,所以在fragmentManager中仍然可以找到,即通过FragmentManager::findViewByTag()仍然是会有值的。 attach():显然这个方法与detach()所做的工作相反,它一方面利用fragment的onCreateView()来重建视图,一方面将此fragment添加到ADD队列中;这里最值得注意的地方在这里:由于是将fragment添加到ADD队列,所以只能添加到列队头部,所以attach()操作的结果是,最新操作的页面始终显示在最前面!这也就解释了下面的例子中,为了fragment2 detach()后,当再次attach()后,却跑到了fragment3的前面的原因。还有,由于这里会将fragment添加到Activity的ADD队列中,所以在这里调用fragment::isAdded()将返回True; 下面用一个例子来讲讲,有关这上面所讲解的知识,效果图如下:

好了,下面就是代码部分了,这部分代码是在上一部分的上面添加了几个按钮而来的,直接看按钮点击时的代码操作:

1、点击frag3 detach按钮的代码

FragmentManager manager = getSupportFragmentManager();Fragment fragment = manager.findFragmentByTag("fragment3");FragmentTransaction transaction = manager.beginTransaction();transaction.detach(fragment);transaction.addToBackStack("detach fragment3");transaction.commit();从代码也可以看到,没什么难度,这个函数的最难点在于知道detach()在执行过程中都干了什么!再重申一遍:一方面删除fragment的View视图;一方面将fragment从Activity的ADD队列中移除!说是Activity的ADD队列,倒不如说是container的ADD队列更贴切些;因为一个Activity上面可以有多个Container来盛装Fragment实例组,每一个Container都会被分配一个ADD队列来记录当前通过add()方法,添加到这个container里的所有fragment实例。2、点击“frag3 attach”按钮的代码FragmentManager manager = getSupportFragmentManager();Fragment fragment = manager.findFragmentByTag("fragment3");FragmentTransaction transaction = manager.beginTransaction();transaction.attach(fragment);transaction.addToBackStack("attach fragment3");transaction.commit();依然,相比以前的fragment操作也只多了一个transaction.attach(fragment);没什么难度。关键仍然在于知道attach()操作都做了哪些事!再次重申:一方面重建fragment的View,注意是重建!另一方面,将fragment实例添加进container的ADD队列中;关于"frag2 detach"和"frag2 attach"的代码就不再贴出来了,跟frag3的一样。好了,到这里,有关Fragment的操作都已经讲完了,下面就讲讲有关在Fragment操作中Android的BUG!

源码在文章底部给出

三、系统BUG——add()和replace()千万不要共用!!!

先写个例子来看一下问题:这个例子分为两部分,

当世界给草籽重压时,它总会用自己的方法破土而出。

管理Fragment(2)

相关文章:

你感兴趣的文章:

标签云: