ViewPager中Fragment的生命周期
来源:互联网 发布:java file.getlength 编辑:程序博客网 时间:2024/06/07 13:08
切换ViewPager时Fragment的生命周期变化
这里有一个MainActivity,MainActivity中有一个ViewPager,使用的适配器是FragmentPagerAdapter,ViewPager中有三个Fragment:FirstFragment,SecondFragment,ThirdFragment。
刚进入MainActivity,Log是这样的:
可以看到,MainActivity按照常规顺序调用后,FirstFragment和SecondFragment先后调用了onAttach()和onCreate()实例化了Fragment,并且在FirstFragment调用onResume()之后,SecondFragment也调用了onResume(),也就是是说SecondFragment已经加载好了,随时准备变为可见,接下来滑动到SecondFragment,是这样的:
然后再滑到第三个ThirdFragment,可以看到:
为什么会这样呢?
原来ViewPager默认会加载当前页面和当前页面左右的两个页面。ViewPager中有一个成员变量纪录着加载的左右页面的数量private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES
,默认值就是private static final int DEFAULT_OFFSCREEN_PAGES = 1
。
我们可以调用如下方法调整默认加载的数量:
/** * Set the number of pages that should be retained to either side of the * current page in the view hierarchy in an idle state. Pages beyond this * limit will be recreated from the adapter when needed. * * <p>This is offered as an optimization. If you know in advance the number * of pages you will need to support or have lazy-loading mechanisms in place * on your pages, tweaking this setting can have benefits in perceived smoothness * of paging animations and interaction. If you have a small number of pages (3-4) * that you can keep active all at once, less time will be spent in layout for * newly created view subtrees as the user pages back and forth.</p> * * <p>You should keep this limit low, especially if your pages have complex layouts. * This setting defaults to 1.</p> * * @param limit How many pages will be kept offscreen in an idle state. */ 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设为0呢?
显然不能,我们发现源码中有这么一段:
if (limit < DEFAULT_OFFSCREEN_PAGES) { Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + DEFAULT_OFFSCREEN_PAGES); limit = DEFAULT_OFFSCREEN_PAGES; }
所以最少加载当前页面的左右各一页,把mOffscreenPageLimit 设为0,ViewPager也会替你修改成1。
当然超出mOffscreenPageLimit 的范围,Fragment的视图就会被销毁。所以就有了上面打印的日志。
实现懒加载
既然ViewPager默认给我们加载当前页面和当前页面左右的两个页面,那该如何实现只加载当前页面呢?
第一个方法,自己复制一份ViewPager的代码,改名为LazyViewPager,然后修改代码,再使用LazyViewPager替代ViewPager。
第二个方法,直接修改ViewPager源码,自己打个v4包。
当然以上两种方法不推荐。
数据的懒加载
其实一般为了避免不必要的流量浪费,像微信一样我们只要实现数据的懒加载即可。
利用setUserVisibleHint(),如下:
public class BaseFragment extends Fragment { protected boolean isViewCreated = false; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return super.onCreateView(inflater, container, savedInstanceState); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (getUserVisibleHint()) { lazyLoadData(); } } /** * 懒加载方法 */ protected void lazyLoadData() { }}
为什么要判断getUserVisibleHint()的值,因为查看FragmentPagerAdapter的源码会发现setUserVisibleHint()第一次调用是在onAttach()之前,这样显然不可以。我们只有等Fragment的视图加载好,才能加载数据。
或者利用Fragment的onHiddenChanged()通过类似的思路也能实现数据的懒加载。
也可以利用ViewPager中OnPageChangeListener接口的onPageSelected(),或者TabLayout中TabLayoutOnPageChangeListener接口的onPageSelected()。
FragmentPagerAdapter和FragmentStatePagerAdapter的区别
之前的案例都是使用的FragmentPagerAdapter,这里讲讲FragmentPagerAdapter和FragmentStatePagerAdapter的区别。
当ViewPager切换的时候,FragmentPagerAdapter会销毁Fragment的视图并且回调onDestroyView(),但是会保存内存中Fragment的实例不会执行onDestroy():
I/fragment: onPause()I/fragment: onStop()I/fragment: onDestroyView()
当ViewPager切换的时候,FragmentStatePagerAdapter不仅会销毁Fragment的视图,而且会删除内存中Fragment的实例并且和Activity解绑:
I/fragment: onPause()I/fragment: onStop()I/fragment: onDestroyView()I/fragment: onDestroy()I/fragment: onDetach()
还有一点就是FragmentStatePagerAdapter会将onSaveInstanceState(Bundle outState)中的Bundle信息保存下来。
也就是说,你可以在onSaveInstanceState(Bundle outState)中保存一些数据,在onCreate()中进行恢复。
FragmentStatePagerAdapter相对于FragmentPagerAdapter节约内存,FragmentStatePagerAdapter类上有如下声明:
* <p>This version of the pager is more useful when there are a large number * of pages, working more like a list view. When pages are not visible to * the user, their entire fragment may be destroyed, only keeping the saved * state of that fragment. This allows the pager to hold on to much less * memory associated with each visited page as compared to * {@link FragmentPagerAdapter} at the cost of potentially more overhead when * switching between pages.
参考:
1.Android Fragment 你应该知道的一切
2.源码探索系列43—关于FragmentStatePagerAdapter和FragmentPagerAdapter
3.使用FragmentPagerAdapter和FragmentStatePagerAdapter时Fragment生命周期区别
4.ViewPager中Fragment的生命周期
5.ViewPager+Fragment生命周期方法(一)
6.死磕 Fragment 的生命周期
7.实现类似微信Viewpager-Fragment的惰性加载,lazy-loading
- viewpager 中fragment 的生命周期
- ViewPager中Fragment的生命周期
- viewpager中fragment生命周期
- viewpager中fragment的生命周期管理
- viewpager中fragment的生命周期管理
- viewpager中fragment的生命周期管理
- ViewPager +Fragment 中Fragment被预加载问题(ViewPager中Fragment的生命周期管理)
- viewpager 中fragment 生命周期问题
- ViewPager里Fragment的生命周期
- ViewPager中的Fragment的生命周期
- 关于ViewPager中显示fragment的生命周期调用问题
- Viewpager中Fragment的生命周期以及方法流程详解
- Fragment的懒加载(解决ViewPager中Fragment生命周期错乱的问题)
- 关于Viewpager中的Fragment的生命周期
- Viewpager和FragmentTransaction、Fragment生命周期的关系
- 关于ViewPager+Fragment中Fragment不销毁/生命周期
- ViewPager嵌套Fragment时Fragment的生命周期问题
- viewpager fragment中fragment的状态保存
- 侧拉菜单传值
- springmvc的ModelAttribute注解
- To enable just-in-time (JIT) debugging错误的解决方式
- Linux 命令之查看和修改机器名称
- Intellij idea使用小坑
- ViewPager中Fragment的生命周期
- opencv开发笔记(十):利用轨迹条调整图像对比度和亮度
- MacOS 开发 -- 程序打包生成dmg
- Lua table 表的操作——只有代码
- Struts2与SpringMVC的区别
- shishi
- php下的原生ajax请求
- ReactNative版本升级
- MySQL day3---操作数据表中的记录