源码分析FragmentPagerAdapter和FragmentStatePagerAdapter的区别

两个基于PagerAdapter的类,都是在ViewPager里面,每次生成Fragment时用到的,只是各自的侧重点不同,FragmentStatePagerAdapter侧重于对于在多页面中展示,需要每次都去处理生成新的Fragment,而FragmentPagerAdapter侧重于展示数量少的页面,对于将展示过的页面(Fragment)存储起来,再次加载时,直接调用内存中的Fragment以达到节省时间和资源的目的。


  1. FragmentPagerAdapter:
    我们主要看一下在初始化Item时候调用到的instantiateItem()方法:
@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?
        //判断请求的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); 
            //调用这个方法来生成新的Fragment
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId)); 
                    //将新生成的Fragment存储起来,以便以后再次用到时,直接attach()
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }

        return fragment;
    }

然后我们再来看下getItem()方法:

/**
     * Return the Fragment associated with a specified position.
     */
    public abstract Fragment getItem(int position);
    //这是一个抽象的方法,需要我们在使用时候自己去实现

最后是destroyItem()方法:

@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); 
        //这里是区别的重点  在销毁Item时候,FragmentPagerAdapter
        //仅仅是调用了detach()方法,断开了连接,但是并没有真正的
        //把Fragment消除掉。
    }

detach()方法的调用,说明在使用FragmentPagerAdapter时候,只有消除整个adapter时候,才能将生成的Fragment都消除掉,不然就会直接在内存中。

2 .FragmentStatePagerAdapter
我们也来看下他的instantiateItem()方法:

@Override
    public Object instantiateItem(ViewGroup container, int position) {
        .
        .
        .
        Fragment fragment = getItem(position);//同样在这里生成Fragment
        .
        .
        .
        return fragment;
    }

getItem()方法也是一样的:

public abstract Fragment getItem(int position);

重点看destroyItem()方法:

@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, mFragmentManager.saveFragmentInstanceState(fragment));
        mFragments.set(position, null);

        mCurTransaction.remove(fragment);
        //当销毁当前显示的页面时,调用了remove()方法,
        //说明Fragment已经被销毁,资源已经被释放了。
        //如果需要再次调用时候,需要去重新生成Fragment
    }

两种都各自有适用的场景,选择合适的就好。

参考:
http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifydatasetchanged-does-not-work.html

你可能感兴趣的:(Android入门学习)