Fragment的生命周期

来源:互联网 发布:勇者之塔魂力进阶数据 编辑:程序博客网 时间:2024/06/03 20:18

Fragment可以用来解决不同屏幕分辨率的适配问题,跟Activity一样,它有自己的生命周期,不过貌似比Activity复杂了点:

这里写图片描述

使用Fragment有两种方法,可以在布局文件中直接使用fragment节点将一个Fragment加载到布局中,也可以使用FragmentManager动态管理布局上的Fragment,而动态管理Fragment,一般是这样子:

        FragmentManager fm = getFragmentManager();        FragmentTransaction ft = fm.beginTransaction();        //ft.add(fragment, tag)        //ft.remove(fragment)        //ft.replace(containerViewId, fragment)        //ft.show(fragment)        //ft.hide(fragment)        ft.commit();

注意需要弄清楚执行不同的操作时会回调那些生命周期函数。
(1)add:onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume
(2)remove:onPause->onStop->onDestroyView->onDestroy->onDetach
(3)replace:实际就是先remove旧的再add新的。
(4)show,hide:不回调任何生命周期函数

Fragment与Activity间的生命周期关系

这里写图片描述

如果在在布局文件中使用静态指定一个fragemnt节点,不使用FragmentManager对其进行管理,那么该Fragment与Activity的生命周期回调函数调用顺序为:
(1)Fragment的onAttach,onCreate,onCreateView是在Activity的onCreate中调用的。
(2)Activity的onCreate执行完就调用Fragment的onActivityCreated。
(3)调用onStart,onResume时先调Activity的再调Fragment;调用onPause,onStop时先调Fragment的再调用Activity。
(4)接下来调用Fragment的onDestroyView,onDestroy,onDetach,最后才调Activity的onDestroy。

Fragment嵌套在ViewPager中时的生命周期

我们有时会使用ViewPager+Fragment实现多屏滑动效果,由于ViewPager有缓存和预加载功能,所以这些Fragment的生命周期也会有所不同。
假设有一个ViewPager嵌套了6个Fragment以实现左右滑动的界面效果,6个Fragment从左到右依次为A,B,C,D,E和F。则:
(1)首次进入界面,看到的是A,这时A就会回调onAttach到onResume一系列的生命周期函数,由于ViewPager有预加载功能,它会预先加载当前Fragment左右mOffscreenPageLimit个Fragment,mOffscreenPageLimit默认为1,因此这时B也会回调onAttach到onResume一系列的生命周期函数。
(2)接着向右滑动一页,现在看到的是B,同样ViewPager会去预加载当前Fragment左右mOffscreenPageLimit个Fragment,由于左边是A刚才已经加载了,因此不用加载A,右边是C还没有被加载,那么就加载C,这时C从onAttach到onResume一系列的生命周期函数会被调用。
(3)继续向右滑动一页,现在看到的是C,同样道理去加载D。不过这时A已经偏离当前显示的Fragment C超过mOffscreenPageLimit了,那么A的View就会被销毁,会回调onPause到onDestroyView一系列回调函数。
(4)如果这时再向左滑回来,此时看到B,那么又会调用A的onCreateView,onActivityCreated,D的onPause,onStop,onDestroyView,A的onStart,onResume。
(5)最后销毁ViewPager时,所有被加载的Fragment都会调用相应回调函数直到onDetach为止。

总的来说:ViewPager会预加载当前Fragment左右mOffscreenPageLimit个Fragment,而距离更远的Fragment如果之前被加载过就会被销毁掉,防止占用太多内存。

mOffscreenPageLimit相关说明:
在ViewPager源码中mOffscreenPageLimit默认为1:

private static final int DEFAULT_OFFSCREEN_PAGES = 1;......private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES;

可以调用setOffscreenPageLimit设置预加载和缓存最大偏移量:

    public void setOffscreenPageLimit(int limit) {        if (limit < DEFAULT_OFFSCREEN_PAGES) {            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +                    DEFAULT_OFFSCREEN_PAGES);            limit = DEFAULT_OFFSCREEN_PAGES;        }        if (limit != mOffscreenPageLimit) {            mOffscreenPageLimit = limit;            populate();        }    }

可以看到mOffscreenPageLimit必须大于等于1,所以如果我们为了提高响应速度,避免占用过多内存不想要预加载和缓存那些看不到的Fragment,可以改写ViewPager相关代码实现懒加载。

0 0
原创粉丝点击