viewpager可以用来实现多个Fragment显示并可左右滑动的功能。ViewPager有两种不同的适配器来显示Fragment,下面将分别探讨这两种显示方式Fragment的生命周期变化有何不同。
布局为上下两个不同apater的ViewPager。
Fragment标识为1A,2B,3C,4D共4个对象,从1A滑动到4D记录并分析对应的生命周期变化。
左右各预先加载一个视图,默认值为1,由下述方法决定
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();
}
}
1.FragmentPagerAdapter
左右滑动时各个Fragment的生命周期变化
//界面初始加载显示1A,预先加载2B界面(一个完整的Fragment生命周期)
09-10 20:47:50.270 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
null:null->onCreate
null:null->onAttach
09-10 20:47:50.276 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
09-10 20:47:50.277 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onCreateView
09-10 20:47:50.284 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onActivityCreated
09-10 20:47:50.285 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onStart
FragmentPager:示例1A->onResume
09-10 20:47:50.286 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onCreateView
09-10 20:47:50.288 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onActivityCreated
09-10 20:47:50.293 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onStart
09-10 20:47:50.294 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onResume
//从1滑动到4
//滑动到2B界面时,预先加载完成3C的界面
09-10 20:49:05.709 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
09-10 20:49:05.710 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
09-10 20:49:05.714 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例3C->onCreateView
09-10 20:49:05.720 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例3C->onActivityCreated
FragmentPager:示例3C->onStart
FragmentPager:示例3C->onResume
//滑动到3C界面时,预先加载4D的Frgment
09-10 20:49:08.020 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
null:null->onCreate
//因为viewpager默认加载是左右各一项,所以当滑动到3C时,1A界面会被销毁
09-10 20:49:08.021 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onPause
FragmentPager:示例1A->onStop
FragmentPager:示例1A->onDestroyView
//销毁完1A视图时开始预先显示4D的界面
09-10 20:49:08.022 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例4D->onCreateView
09-10 20:49:08.026 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例4D->onActivityCreated
FragmentPager:示例4D->onStart
09-10 20:49:08.027 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例4D->onResume
//滑动到4D时,销毁2B的视图
09-10 20:49:09.626 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onPause
FragmentPager:示例2B->onStop
FragmentPager:示例2B->onDestroyView
2.FragmentStatePagerAdapter
//界面初始加载显示1A,预先加载2B界面(一个完整的Fragment生命周期)
09-10 20:47:50.297 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
null:null->onCreate
09-10 20:47:50.298 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
09-10 20:47:50.299 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
09-10 20:47:50.300 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onCreateView
09-10 20:47:50.305 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onActivityCreated
09-10 20:47:50.307 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onStart
FragmentState:示例1A->onResume
09-10 20:47:50.308 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onCreateView
09-10 20:47:50.312 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onActivityCreated
09-10 20:47:50.314 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onStart
FragmentState:示例2B->onResume
//从1滑动到4
//滑动到2B界面时,预先加载完成3C的界面
09-10 20:50:37.133 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
09-10 20:50:37.134 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
FragmentState:示例3C->onCreateView
09-10 20:50:37.138 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例3C->onActivityCreated
09-10 20:50:37.140 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例3C->onStart
FragmentState:示例3C->onResume
//滑动到3C界面时,先保存将要销毁的1A的状态,后再预先加载4D的Frgment
09-10 20:50:38.863 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onSaveInstanceState
09-10 20:50:38.867 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
null:null->onCreate
//开始执行1A的销毁过程
09-10 20:50:38.869 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onPause
FragmentState:示例1A->onStop
FragmentState:示例1A->onDestroyView
//FragmentState会将1A的对象给销毁掉,而FragmentPager只会销毁视图,所以以下方法FragmentPager将不会执行
09-10 20:50:38.870 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onDestroy
FragmentState:示例1A->onDetach
//销毁完1A视图时开始预先显示4D的界面
09-10 20:50:38.871 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例4D->onCreateView
09-10 20:50:38.876 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例4D->onActivityCreated
FragmentState:示例4D->onStart
09-10 20:50:38.877 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例4D->onResume
//滑动到4D时,销毁2B的Fragment对象
09-10 20:50:40.150 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onSaveInstanceState
09-10 20:50:40.153 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onPause
FragmentState:示例2B->onStop
FragmentState:示例2B->onDestroyView
09-10 20:50:40.156 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onDestroy
09-10 20:50:40.157 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onDetach
3.总结
- FragmentPagerAdapter只是销毁Fragment的视图,对象并未销毁,继续由Activity持有。而FragmentStatePagerAdapter则会销毁Fragment的对象,Activity不再持有该Fragment对象。
- FragmentPagerAdapter适用于显示较少Fragment的情况,
- FragmentStatePagerAdapter最大的特点是Fragment将会执行onSaveInstanceState保存状态,并且是在onPause()之前执行
4.源码分析
两者的主要区别在于
FragmentPagerAdapter
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
+ " v=" + ((Fragment)object).getView());
//Detach the given fragment from the UI,只是移除Fragment的视图
mCurTransaction.detach((Fragment)object);
}
FragmentStatePagerAdapter
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment) object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
+ " v=" + ((Fragment)object).getView());
while (mSavedState.size() <= position) {
mSavedState.add(null);
}
mSavedState.set(position, fragment.isAdded()
? mFragmentManager.saveFragmentInstanceState(fragment) : null);
mFragments.set(position, null);
//直接移除Fragment对象
mCurTransaction.remove(fragment);
}