android FragmentPagerAdapter与FragmentStatePagerAdapter的区别

很多app的主界面都是底部几个按钮,然后点击切换显示不同的UI展现,这种可以使用Viewpager+fragment的方式实现,但是一不注意就会有问题,

比如是使用FragmentPagerAdapter的话,如果viewpager设置了setCurrentItem(index);会先把index-1,index+1以及index中对应的Fragment中的view加载出来,如果index=0的话,就只加载2个fragment中的view了.当viewpager滑动到那个界面就会加载那个fragment的view,比如你从第一个滑动到第四个,然后又从第四个滑动到第一个,这个时候第四个view就会被回收,view就为null,意味着你来回切换,fragment中的view会重复的,因为之前Fragment中的onDestroyView()生命周期方法会执行,导致view就会被回收了,如果你再viewpager的滑动监听通过view做什么业务很容易导致NullPointerException异常,我之前项目就有遇到过,重复加载view的问题怎么解决呢?

第一:设置viewpager的缓存为你fragment的个数.

viewpager.setOffscreenPageLimit(fragment的个数);

这些现象,你可以通过打log自己去分析,

如果使用的是FragmentStatePagerAdapater,viewpager滑动的时候会把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);
}

最后一行就是移除了Fragment,而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());
    mCurTransaction.detach((Fragment)object);
}

最后一行就是把Fragment中View移除了,这就是二者很大的区别,所以说当Fragment比较多的时候就用FragmentStatePagerAdapter,因为它会之前的Fragment从内存中移除,这样就节省了内存,如果Fragment不多的情况下就使用FragmentPagerAdapter,

还有一个问题就是动态的加载Fragment,就是viewpager增加或者删除Fragment,这个在我项目中也遇到了,如果是FragmentStatePagerAdapter的话就要重写

@Override
public int getItemPosition(Object object) {
    return PagerAdapter.POSITION_NONE;
}

如果是FragmentPagerAdapter的话就要重写:

@Override
public long getItemId(int position) {
    int hashCode = mFragment.get(position).hashCode();
    return hashCode;
}
然后记得把viewpager指向显示那一个fragment,比如viewpager.setCurrentItem(0);如果不调用这个,会发现他还是会显示当前删除的fragment,只有滑动后,那个fragment才会消失.





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值