FragmentStatePagerAdapter与FragmentPagerAdapter

ViewPager与Fragment的配合使用,除了FragmentPagerAdapter之外,还有另外一个选择FragmentStatePagerAdapter。
其实在实际应用中FragmentStatePagerAdapter相对于FragmentPagerAdapter多了两个全局变量:

private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();

在这个地方,需要注意的是:

①mSavedState 保存每个Fragment的状态信息的列表
②mFragments 保存每个Fragment实例对象的列表

接下来,贴出来源码分析一波:

 /*** 获取给定位置对应的Fragment。
 ** @param position 给定的位置
 * @return 对应的Fragment
 * */
 public abstract Fragment getItem(int position);
 @Override
 public void startUpdate(ViewGroup container) {}
 @Override
 public Object instantiateItem(ViewGroup container, int position) { 
     // 获取给定位置的已存在Fragment 
     if (mFragments.size() > position) { 
         Fragment f = mFragments.get(position); 
         if (f != null) {
           return f;
          } 
       }
    // 创建新事务
     if (mCurTransaction == null) {
         mCurTransaction = mFragmentManager.beginTransaction(); 
      } 
      // 创建给定位置的Fragment 
      Fragment fragment = getItem(position); 
      if (DEBUG) 
      Log.v(TAG, "Adding item #" + position + ": f=" + fragment); 
      // 读取给定位置的Fragment保存的状态,并用该状态对Fragment进行初始化 
      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);
      // 添加Fragment到FragmentManager中 
     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);
               } 
           // 保存当前销毁的Fragment的状态 
           mSavedState.set(position, fragment.isAdded() ? mFragmentManager.saveFragmentInstanceState(fragment) : null); 
           mFragments.set(position, null); 
           // 移除销毁的Fragment 
           mCurTransaction.remove(fragment); }
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment)object;
    if (fragment != mCurrentPrimaryItem) {
        // 主要项切换,相关菜单及信息进行切换
        if (mCurrentPrimaryItem != null) {
            mCurrentPrimaryItem.setMenuVisibility(false);
            mCurrentPrimaryItem.setUserVisibleHint(false);
        }
        if (fragment != null) {
            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
        }
        mCurrentPrimaryItem = fragment;
    }
}

@Override
public void finishUpdate(ViewGroup container) {
    if (mCurTransaction != null) {
        // 提交事务
        mCurTransaction.commitAllowingStateLoss();
        mCurTransaction = null;
        // 立即运行等待中事务
        mFragmentManager.executePendingTransactions();
    }
}

@Override
public boolean isViewFromObject(View view, Object object) {
    return ((Fragment)object).getView() == view;
}

@Override
public Parcelable saveState() {
    Bundle state = null;
    if (mSavedState.size() &gt; 0) {
        // 保存Fragment状态列表
        state = new Bundle();
        Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
        mSavedState.toArray(fss);
        state.putParcelableArray("states", fss);
    }
    // 保存Fragment列表
    for (int i=0; i&lt;mFragments.size(); i++) {
        Fragment f = mFragments.get(i);
        if (f != null &amp;&amp; f.isAdded()) {
            if (state == null) {
                state = new Bundle();
            }
            String key = "f" + i;
            mFragmentManager.putFragment(state, key, f);
        }
    }
    return state;
}

@Override
public void restoreState(Parcelable state, ClassLoader loader) {
    if (state != null) {
        // 读取Fragment状态列表
        Bundle bundle = (Bundle)state;
        bundle.setClassLoader(loader);
        Parcelable[] fss = bundle.getParcelableArray("states");
        mSavedState.clear();
        mFragments.clear();
        if (fss != null) {
            for (int i=0; i&lt;fss.length; i++) {
                mSavedState.add((Fragment.SavedState)fss[i]);
            }
        }
        // 读取Fragment列表
        Iterable&lt;String&gt; keys = bundle.keySet();
        for (String key: keys) {
            if (key.startsWith("f")) {
                int index = Integer.parseInt(key.substring(1));
                Fragment f = mFragmentManager.getFragment(bundle, key);
                if (f != null) {
                    while (mFragments.size() &lt;= index) {
                        mFragments.add(null);
                    }
                    f.setMenuVisibility(false);
                    mFragments.set(index, f);
                } else {
                    Log.w(TAG, "Bad fragment at key " + key);
                }
            }
        }
    }
}

从源代码中,我们可以清楚了解到FragmentStatePagerAdapter与FragmentPagerAdapter的不同:

  • FragmentStatePagerAdapter对Fragment实例和Fragment状态进行引用保留。

  • FragmentStatePagerAdapter在instantiateItem方法中,创建新Fragment后,读取对应Fragment状态对其进行初始化设置,并且只使用到add方法。

  • FragmentStatePagerAdapter在destroyItem方法中,销毁Fragment时,保存其Fragment状态,并且使用remove方法移除Fragment。

  • FragmentStatePagerAdapter重载了saveState方法和restoreState方法,在其中对于Fragment实例列表和Fragment状态列表进行保存和读取。

通过运行结果分析可以得到:

  • 当Fragment重新被add时,Fragment的生命周期全部重新调用,但是savedInstanceState参数保留着之前存储的数据。

  • Fragment在FragmentStatePagerAdapter类的destroyItem方法中被remove时,Fragment的onDestroy方法和onDetach方法都被调用到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值