ViewPager动态更新及两种PagerAdapter的内在区别

来源:互联网 发布:省钱小管家软件 编辑:程序博客网 时间:2024/04/29 17:23

简介

新闻类应用大多都会有类似标签切换的功能,具体效果类似:网易新闻,今日头条等,一般的实现方案都是采用的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_UNCHANGEDPOSITION_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;        }    }

扩展阅读
Update ViewPager dynamically?

如何更新及替换ViewPager中的Fragment

0 0