美文网首页安卓开发
FragmentPagerAdapter和FragmentSta

FragmentPagerAdapter和FragmentSta

作者: 遇见初夏 | 来源:发表于2019-01-14 13:50 被阅读0次

    首先我们来比较一下两者在加载和销毁fragment item时都做了什么:

    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);
                if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
                mCurTransaction.add(container.getId(), fragment,
                        makeFragmentName(container.getId(), itemId));
            }
            if (fragment != mCurrentPrimaryItem) {
                fragment.setMenuVisibility(false);
                fragment.setUserVisibleHint(false);
            }
            return fragment;
        }
    

    在instantiateItem方法中,主要是将Fragment添加到FragmentManager中。未添加到FragmentManager中的执行add操作,已添加到FragmentManager中的只进行attach操作。

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

    在destroyItem方法中,只是进行detach操作。detach操作并不会将Fragment销毁,Fragment依旧是由FragmentManager进行管理。

    FragmentStatePagerAdapter源码:

     @Override
        public Object instantiateItem(ViewGroup container, int position) {
            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 (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + 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);
            mCurTransaction.add(container.getId(), fragment);
            return fragment;
        }
    

    FragmentStatePagerAdapter是通过一个mFragments数组来存储fragment的,通过mSavedState数组来存储fragment销毁时的状态,通过position获取到的fragment可能为空(被回收),如果为空,则会再次调用getItem方法重新创建新的fragment,然后将mSavedState中存储的状态重新赋予这个新的fragment, 达到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);
        }
    

    当item在页面中不可见时,该fragment的状态会先被保存到mSavedState中,而fragment实例则会被销毁。

    相同点:

    两者都会保持当前item(即fragment)和前后的item的状态。
    显示当前item的同时,Adapter会提前初始化后一个item,并把当前item的前一个item保存在内存中。

    不同点:

    在于fragment 存储、恢复、销毁 的方式不同

    对滑动过去的页面是否销毁:
    例如:依次从左向右有fragment1,fragment2,fragment3三个页面

    FragmentPagerAdapter在滑动到fragment3时,fragment1会依次调用onPause()、onStop()、onDestroyView(),再向左滑动到fragment2时,fragment1会调用onCreateView()、onActivityCreated()、onStart()、onResume()。
    结论:FragmentPagerAdapter会保留页面的状态,并不会完全销毁掉。

    FragmentStatePagerAdapter在滑动到fragment3时,fragment1会依次调用onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()方法,再向左滑动到fragment2时,fragment1会调用onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()、onResume()。
    结论:FragmentStatePagerAdapter会完全销毁滑动过去的item,当需要初始化的时候,会重新初始化页面。

    如何选择?

    当Viewpager中fragment数量多的时候用FragmentStatePagerAdapter,反之则用FragmentPagerAdapter

    相关文章

      网友评论

        本文标题:FragmentPagerAdapter和FragmentSta

        本文链接:https://www.haomeiwen.com/subject/dwuddqtx.html