欢迎来到破竹的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。

小结Fragment与FragmentPagerAdapter的生命周期及其关系

本博客部分内容是来自http://blog.csdn.net/dreamzml/article/details/9951577


FragmentPagerAdapter

FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。如文档所述,该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter。FragmentPagerAdapter 重载实现了几个必须的函数,因此来自 PagerAdapter 的函数,我们只需要实现 getCount(),即可。且,由于 FragmentPagerAdapter.instantiateItem() 的实现中,调用了一个新增的虚函数 getItem(),因此,我们还至少需要实现一个 getItem()。因此,总体上来说,相对于继承自 PagerAdapter,更方便一些。

    getItem()
        该类中新增的一个虚函数。函数的目的为生成新的 Fragment 对象。重载该函数时需要注意这一点。在需要时,该函数将被 instantiateItem() 所调用。
        如果需要向 Fragment 对象传递相对静态的数据时,我们一般通过 Fragment.setArguments() 来进行,这部分代码应当放到 getItem()。它们只会在新生成 Fragment 对象时执行一遍。
        如果需要在生成 Fragment 对象后,将数据集里面一些动态的数据传递给该 Fragment,那么,这部分代码不适合放到 getItem() 中。因为当数据集发生变化时,往往对应的 Fragment 已经生成,如果传递数据部分代码放到了 getItem() 中,这部分代码将不会被调用。这也是为什么很多人发现调用 PagerAdapter.notifyDataSetChanged() 后,getItem() 没有被调用的一个原因。
    instantiateItem()
        函数中判断一下要生成的 Fragment 是否已经生成过了,如果生成过了,就使用旧的,旧的将被 Fragment.attach();如果没有,就调用 getItem() 生成一个新的,新的对象将被 FragmentTransation.add()。
        FragmentPagerAdapter 会将所有生成的 Fragment 对象通过 FragmentManager 保存起来备用,以后需要该 Fragment 时,都会从 FragmentManager 读取,而不会再次调用 getItem() 方法。
        如果需要在生成 Fragment 对象后,将数据集中的一些数据传递给该 Fragment,这部分代码应该放到这个函数的重载里。在我们继承的子类中,重载该函数,并调用 FragmentPagerAdapter.instantiateItem() 取得该函数返回 Fragment 对象,然后,我们该 Fragment 对象中对应的方法,将数据传递过去,然后返回该对象。
        否则,如果将这部分传递数据的代码放到 getItem()中,在 PagerAdapter.notifyDataSetChanged() 后,这部分数据设置代码将不会被调用。
    destroyItem()
        该函数被调用后,会对 Fragment 进行 FragmentTransaction.detach()。这里不是 remove(),只是 detach(),因此 Fragment 还在 FragmentManager 管理中,Fragment 所占用的资源不会被释放。

FragmentPagerAdapter默认是先预加载一页的,比如显示了第1页,就会把第2页也加载了,先调用FragmentPagerAdapter的构造方法 MyPagerAdapter(FragmentManager fm),再调用instantiateItem(ViewGroup container, int position) 函数中判断一下要生成的 Fragment 是否已经生成过了,如果生成过了,就使用旧的,旧的将被 Fragment.attach();如果没有,就调用 getItem() 生成一个新的,然后再调用ChatFragment与foundFragment的生命周期

转载自:https://blog.csdn.net/fangkailong/article/details/38268509

 

FragmentManager的一些api:
不同的FragmentManager:

见其名,知其意,是关于Fragment的管理器,在开发中,使用比较多;
其中关于Manager,用的比较多的API:
- getSupportFragmentManager():在Activity中使用Fragment的管理器,对所有Fragment进行管理。
- getFragmentManager():与 getSupportFragmentManager()功能是一样的,只是是在Fragment中使用
- getChildFragmentManager():在Fragment嵌套使用中经常使用到,但这里需要注意一个点,看下图:

解析图
在fragment创建childFragment的时候,需要注意的是:使用getChildFragmentManager() 使用getFragmentManager()会导致内存泄漏,在嵌套的Fragment中,内部的fragment创建,需要使用getChildFragmentManager()
FragmentManager常用的api:

    getFragments():可以获取所有创建时候add进去的所有Fragment;通常可以通过这个api来获取需要指定操作的fragment对象

    manager.findFragmentByTag(String tag): 通过TAG获取指定的Fragment;这个TAG,是在创建Fragment时,调用addToBackStack(String tag)进行绑定关系的

    popBackStack(): 弹出栈顶fragment

    popBackStack(String tag,int flags):
        tag可以为null或者相对应的tag,flags只有0和1(POP_BACK_STACK_INCLUSIVE)两种情况
        如果tag为null,flags为0时,弹出回退栈中最上层的那个fragment。
        如果tag为null ,flags为1时,弹出回退栈中所有fragment。
        如果tag不为null,那就会找到这个tag所对应的fragment,flags为0时,弹出该
        fragment以上的Fragment,如果是1,弹出该fragment(包括该fragment)以
        上的fragment。

    popBackStackImmediate相关的方法与上面逻辑是一样的与上面不同的是,在调用的时候会立即执行弹出。

FragmentTransaction:

管理着Fragment所有的展示交互,还有Fragment的回滚事件
FragmentTransaction常用的api:

    add():将一个Fragment实例对象添加到集合列表的尾部,当展示的时候会在activity的最上层
    remove():将一个Fragment实例对象从存储的集合列表中移除,并且将其从UI界面中销毁
    replace():将上一个Fragmnt的实例对象从存储的集合列表中移除,将当前的Fragment实例对象添加到存储的链表尾部,当展示的时候会在activity的最上层
    hide():将一个fragment,从展示状态隐藏起来,实例对象不被销毁
    show():将一个fragment实例对象,展示出来

    addToBackStack():将fragment添加到回退栈中

    add() 和 replace() 运用总结:

    在项目的使用中,通常习惯使用add()加载,add方式视图不会重建,会被保存起来,而replace()每次都会remove掉前面的视图,而replace方式的回退,旧的视图每一次都会重建,在用户体验上不好。

    add()和replace()的使用,不能够混合使用,在混合使用的情况下,会导致回退栈混乱,导致的原因是在回退过程中记录的角标存在问题

    hide() 和 show() 运用总结:

    通常的使用情况是在主界面上,有多Tab键切换情况

FragmentTransaction事儿需要用到的api:

    detach():将视图View和Fragment分离,视图View也会从ViewTree中删除,还会将Fragment从add的队列中删除,所以在调用isAdd方法的时候返回的是false,但实例对象本身是还存在的,通过FragmentManager的findFragmentByTag还可以获取到实例对象。
    attach():通过fragment的onCreateView()的重建视图,并且被重新加入到add的队列中,并且处于队列头部。

 

转载自:https://blog.csdn.net/qq_20280683/article/details/79641182

posted @ 2019-12-24 00:30  破竹  阅读(863)  评论(0编辑  收藏  举报