您的位置:首页 > 编程语言 > PHP开发

FragmentPagerAdapter和FragmentStatePagerAdapter 使用场景及源码分析

2016-06-13 16:47 761 查看
        FragmentPagerAdapter 和FragmentStatePagerAdapter  内部都封装有FragmentManager和FragmentTransaction,用于管理Fragment;

使用Fragment 来表示一页,显得更加简单和直观,Fragment  本身提供的一些特性可以让我们方便的对每一页进行管理,使用FragmentManager可以根据ID或TAG来查找Fragment ,
动态添加、删除、替换,Fragment  可以管理自己的生命周期,像Activity一样提供了一些生命周期回调方法

       让Fragment 成为ViewPager的一页时,FragmentManager会一直保存管理创建好了的Fragment,即使当前不是显示的这一页,Fragment对象也不会被销毁,在后台默默等待重新显示。但如果Fragment不再可见时,它的视图层次会被销毁掉,下次显示时视图会重新创建

首先来分析一下FragmentPagerAdapter:

@Override
public Object instantiateItem(ViewGroup container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}

final long itemId = getItemId(position);

// Do we already have this fragment?
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
mCurTransaction.attach(fragment);
} else {
fragment = getItem(position);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), itemId));
}
return fragment;
}

在FragmentPagerAdapter 里的instantiateItem方法实例化Fragment,首先通过TAG去找Fragment是否存在,如果不存在调用getItem()添加,子类需要复写getItem()

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());
mCurTransaction.detach((Fragment)object);
}

在destroyItem()方法中仅仅是把Fragment detach掉,Fragment界面被销毁,但是Fragment还在内存中没有销毁

 因此在使用FragmentPagerAdapter  时,Fragment对象会一直存留在内存中,所以当有大量的显示页时,就不适合用FragmentPagerAdapter 了,FragmentPagerAdapter  适用于只有少数的page情况,像选项卡

接下来看FragmentStatePagerAdapter 源码:

@Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do.  This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}

if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}

Fragment fragment = getItem(position);

if (mSavedState.size() > position) {
Fragment.SavedState fss = mSavedState.get(position);
if (fss != null) {
fragment.setInitialSavedState(fss);
}
}
while (mFragments.size() <= position) {
mFragments.add(null);
}
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
mFragments.set(position, fragment);
mCurTransaction.add(container.getId(), fragment);

return fragment;
}


@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);

mCurTransaction.remove(fragment);
}


从源码上看当使用FragmentStatePagerAdapter 
时,如果Fragment不显示,那么Fragment对象会被销毁,但在回调onDestroy()方法之前会回调onSaveInstanceState(Bundle outState)方法来保存Fragment的状态,下次Fragment显示时通过onCreate(Bundle savedInstanceState)把存储的状态值取出来,FragmentStatePagerAdapter  比较适合页面比较多的情况,像一个页面的ListView
  item
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息