一、前言
- 日常开发中使用ViewPager+Fragment搭建页面很方便,但是ViewPager的缓存问题会导致设置数据后,Fragment中数据更新不及时,可谓让开发者又爱又恨。
二、解决方案
1、创建实例化Fragment的方法,并且每次创建Fragment实例都使用该方法创建
public static CategoryListFragment newInstance(int pageType, Category parentCategory) {
CategoryListFragment f = new CategoryListFragment();
Bundle b = new Bundle();
b.putInt("pageType", pageType);
b.putSerializable("parentCategory", parentCategory);
f.setArguments(b);
return f;
}
2、Fragment参数的获取
- 一定要在onCreate()方法中获取参数,因为在onCreateView()中获取参数,会导致某些状态下,获取不到数据,导致数据丢失
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
pageType = args.getInt("pageType");
parentCategory = (Category) args.getSerializable("parentCategory");
}
}
3、在Fragment中对外提供更新数据的方法,要监听ViewPager滑动事件,同是调用Fragment中方法更新Fragment中数据
public void updateArguments(int pageType, Category parentCategory) {
this.pageType=pageType;
this.parentCategory=parentCategory;
Bundle args = getArguments();
if (args != null) {
args.putInt("pageType", pageType);
args.putSerializable("parentCategory", parentCategory);
}
}
4、ViewPager的adapter已使用FragmentStatePagerAdapter为例子
- 重写getItem方法
override fun getItem(position: Int): Fragment {
return mFragmentList[position % (mFragmentList.size)]
}
- 重写getItemPosition方法
override fun getItemPosition(`object`: Any): Int {
return POSITION_NONE
}
三、总结
- 产生原因:ViewPager缓存导致 int DEFAULT_OFFSCREEN_PAGES = 1,默认缓存条目为1条
- getItemPosition方法中返回POSITION_NONE,默认不缓存,直接刷新数据
四、查看源码
public static final int POSITION_UNCHANGED = -1;
public static final int POSITION_NONE = -2;
public int getItemPosition(@NonNull Object object) {
return -1;
}
源码中默认返回了-1,默认认为POSITION_UNCHANGED,为了效率会默认缓存数据,导致数据更新不及时,甚至不更新,为了解决该缓存问题,我们设置默认不缓存即可,保证数据的及时性,但这样做也牺牲了一部分效率。