android view重新加载数据库,Android ViewPager的FragmentPagerAdapter中Fragment不重新加载数据,并且使用的是其他缓存的Framgnet的问题...

本文揭示了在使用FragmentPagerAdapter时,Fragment数据错位的原因——不当使用position作为Fragment Tag,可能导致重复。作者提供了修改getItemId和重写instantiateItem的方法来确保唯一标识,同时解释了为何暴力重写不是最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

场景:几个相同的页面,要左右切换,比如:天气3的首页

ViewPager使用FragmentPagerAdapter,新添加进adapter中的数据没有问题,而删除数据减少数据之后,Fragment的数据内容没有对号入座,没有变化,而内容显示的是其他已经删除的Fragment的数据。

已经急不可耐的小伙伴可以翻到文末查看解决方法

为什么会导致这个原因呢,是因为之前的Fragmet是缓存在内存中的,翻看FragmentPagerAdapter源码可以看到

@OverridepublicObject instantiateItem(ViewGroup container, intposition) {

if(mCurTransaction== null) {

mCurTransaction= mFragmentManager.beginTransaction();}

final longitemId = 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);}

returnfragment;}

如果Fragment不存在,那么会调用getItem方法重新取得Fragment,并且添加进事务管理中,也就是缓存在内存中,等待Activity被销毁之后才释放,反之已经存在的Fragment将不在重新创建,所以有时getItem方法有时候没有回调的原因就是因为,已经取了缓存内的数据了。

诸位看到这里是不是感觉找到真正原因了,其实不然!

毫于疑问这段代码完全没有问题,那问题出在哪儿呢?

相信诸位已经注意到了makeFragmentName这个方法,每个新添加的Fragment都添加了一个Tag。

final longitemId = getItemId(position);// Do we already have this fragment?String name = makeFragmentName(container.getId(),itemId);Fragment fragment = mFragmentManager.findFragmentByTag(name);

正是通过这个Tag才能让做到让每个Fragment是唯一的。问题就出在Tag上!

相信有许多小伙伴都习惯这样写,把getItemId的返回值直接返回position:

@Overridepublic longgetItemId(intposition) {

returnposition;}

那么问题来了,position有没有可能重复呢,答案当然是肯定的。正是添加的Fragment以position的名义打上了Tag,下一次数据减少的时候,又通过相同的position拿到了相同的Fragment,这里就也就重复了。

有点乱,举个粟子:

efcb1f1539454c5e386bf797ceb52cc9.png

看到这里答案已经明显了,因为传的ID不对,所以导致取小花的时候把小明遗留在内存的Fragment取出来了,而导致了Fragment取错的原因。

代码很简单:

1、重写getItemId方法(推荐)

@Overridepublic longgetItemId(intposition) {

return这里换成自己的唯一ID;}

2、暴力重写instantiateItem与destroyItem(不推荐)

@Overridepublic voiddestroyItem(ViewGroup container, intposition,Object object) {

container.removeView(((Fragment) object).getView());// 移出viewpager两边之外的page布局}

@OverridepublicObject instantiateItem(ViewGroup container, intposition) {

Fragment fragment = getItem(position);if(!fragment.isAdded()) { // 如果fragment还没有addedFragmentTransaction ft = mFragmentManager.beginTransaction();ft.add(fragment,fragment.getClass().getSimpleName());ft.commit();mFragmentManager.executePendingTransactions();//同步的方式添加Fragment}

if(fragment.getView().getParent() == null) {

container.addView(fragment.getView());// 为viewpager增加布局}

returnfragment;}

如果有说得不对的地方请诸位指出,共同学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值