FragmentPagerAdapter.notifyDataSetChanged失效详解

来源:互联网 发布:linux setlocale 函数 编辑:程序博客网 时间:2024/06/16 07:39

背景

项目中用到Viewpager+FragmentPagerAdapter管理若干Fragment,我的fragments是根据服务返回的json动态生成的,当我的fragments发生变化时,本想通过

fragments.clear();//清除旧的fragmentfragments.add(……);//添加新的FragmentPagerAdapter.notifyDataSetChanged

来替换原来的fragments,但是结果是,并无反应,还是原来的fragments

网上关于这一块,解决方案很多,特别是说在FragmentPagerAdapter中重写getItemPosition强制返回POSITION_NONE的:

@Overridepublic int getItemPosition(Object object) {     return POSITION_NONE; } 

这些我都已经处理过了,但是还是会出现这种情况。

根据以往的经验,还是看一看源码吧!

源码追踪

我们看看FragmentPagerAdapterinstantiateItem方法:

@Overridepublic 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));    }    ……    return fragment;}

重点在于:

String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = mFragmentManager.findFragmentByTag(name);

也就是说FragmentManager会缓存原来的fragment,这里是优先取缓存的!

所以很显然,我只清理了fragment列表,但是没有清理缓存,结果依然是显示旧的fragments

解决方案

解决方案就很简单了,在FragmentActivity中清理缓存,我这里是android v4包:

getSupportFragmentManager().getFragments().clear();

如此便解决了一个烦人的问题。

后记

有时候一个bug的产生,是由于你对系统的理解不深,android对很多细节都有优化手段,而我们在使用过程中,稍不注意,就会忽略这些优化,很容易造成一些莫名其妙的bug

bug产生时,除了焦头烂额的google、百度,不妨也尝试着阅读源码,说不定就茅塞顿开了呢。

阅读全文
2 0
原创粉丝点击