简介
新闻类应用大多都会有类似标签切换的功能,具体效果类似:网易新闻,今日头条
等,一般的实现方案都是采用的ViewPager+Fragment
来实现,伴随着Fragment
之上标签(通常都是采用类似TabLayout
类的控件来实现)的 增 删 改
,下方的Viewpager
也需要更新.
notifyDataSetChanged
有关ViewPager
的刷新问题,网上也有很多的介绍,像这类的集合视图,一般采用的方式都是Adapter+ Observable
模式.
通过查看ViewPager
的源码,可以看到更新的主要逻辑在ViewPager#PagerObserver
中:
...
for (int i = 0; i < mItems.size(); i++) {
final ItemInfo ii = mItems.get(i);
final int newPos = mAdapter.getItemPosition(ii.object);
if (newPos == PagerAdapter.POSITION_UNCHANGED) {
continue;
}
if (newPos == PagerAdapter.POSITION_NONE) {
...
continue;
}
...
}
...
这里需要注意的是POSITION_UNCHANGED
和POSITION_NONE
的含义,官网有介绍,
- 每次调用
notifyDataSetChanged()
方法时,都会激活getItemPosition
方法 POSITION_NONE
表示该Item
会被destroyItem
方法remove
掉,然后重新加载,POSITION_UNCHANGED
表示不会重新加载,默认是POSITION_UNCHANGED
##FragmentPagerAdapter&&FragmentStatePagerAdapter
- FragmentPagerAdapter: 所有的
Fragment
实例一直保存在Fragment manager
中,适用于少量固定的fragment
,当Fragment
不可见时,它的视图会被销毁. - 当
adapter
需要一个指定位置的Fragment
时,并且这个Fragment
不存在时,getItem
就被调到. - FragmentStatePagerAdapter: 当
Fragment
不可见时,整个Fragment
实例都会被销毁,saveState()
方法会被调用(用于下次恢复Fragment
实例) - 使用
FragmentPagerAdapter
时,当每页的Fragment
被创建后,getItem()
不会被调到了 - 对于
FragmentStatePagerAdapter
,由于Fragment
被销毁,所以每次都会调用getItem()
来判断是否要重新加载.
常见使用上的误区
- ViewPager.getChildCount() :当前没有被销毁视图的Fragment的个数.
- ViewPager.getAdapter().getCount(): 所有的Fragment数量
- instantiateItem的返回值是Object,并不是一定要是当前
Fragment
,这个返回结果
会被传递到isViewFromObject(View view, Object object)
方法的第二个参数中,因此只要保证能对应即可.
ViewPager动态刷新办法
最终的解决办法,为了保证Fragment
重建,和getItem
会被调用,采用FragmentStatePagerAdapter
,对于getItemPosition
方法,
需要保证已存在的Fragment
复用,不存在的刷新重建.可如下实现.
public int getItemPosition(Object item) {
MyFragment fragment = (MyFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);
if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}