PagerAdapter 数据的增删改

一:PagerAdapter#notifyDataSetChanged调用过程


PagerAdapter#notifyDataSetChanged方法源码

注:这里会通过mViewPagerObserver.onchanged()回调通知viewpager


ViewPager#setadapter方法源码

注:前面调用adapter的回调通知 是在Viewpager#setadapter方法时通过this.mAdapter.setViewPagerObserver(this.mObserver);给adapter注册的回调


ViewPager#PagerObserver类

注:PagerObserver是Viewpager的一个内部类,所以notifyDataSetChanged的时候最终会调用ViewPager#dataSetChanged方法


ViewPager#dataSetChanged部分源码

注:ViewPager#dataSetChanged 才是 adapter数据刷新的处理,要先找到这里才能开始分析。


Viewpager静态内部类Iteminfo


Viewpager#setCurrentItemInternal
Viewpager#populate部分源码



二:fragmentStateAdapter 数据修改:

1.增:

    方法:viewpager#dataSetChanged:

   1. boolean needPopulate = this.mItems.size()

    2.newPos   = - 1(viewpager内部默认-1,用户可修改)

    3.if(newPos == -1) 什么事情都不做

    4.if(newPos == -2) 会对viewpager中的mItems进行remove然后      mAdapter.destroyItem  同时更新viewpager当前页(增的情况下,不变)。随后needPopulate =true

   5.if(needPopulate){

    this.setCurrentItemInternal(newCurrItem,false,true);

     this.requestLayout();

 }

  6.setCurrentItemInternal方法内部根据mFirstLayout判断是否执行this.populate(item);(mFirstLayout = false)

  7.populate会根据当前的页码数和用户设置的mOffscreenPageLimit和ItemInfo中的widthFactor计算需不需要去执行Viewpager#addNewItem();

  8.addNewItem 会去执行adapter.instantiateItem()方法;

结论1:if(newPos == -2) 会让viewpager清除ArrayList mItems 的内容。同时this.mAdapter.destroyItem(this, ii.position, ii.object);

结论2(仅仅只是增长adapter集合):notifyDataSetChanged 必定会调用populate方法,假如mItems是空的(newpos == -2),必定会去addnewitem同时this.mAdapter.instantiateItem(this, position);假如newpos == -1的情况,会根据当前页和viewpager偏移值去判定需不需要调用addnewitem。

结论3:仅仅只是增长adapter集合viewpager不会有问题;

2.改(不增加和减少adapter中数据的长度):

1. boolean needPopulate = this.mItems.size()

    2.newPos   = - 1(viewpager内部默认-1,用户可修改)

    3.if(newPos == -1) 什么事情都不做

    4.if(newPos == -2) 会对viewpager中的mItems进行remove然后      mAdapter.destroyItem  同时更新viewpager当前页(改的情况下,不变)。随后needPopulate =true

   5.if(needPopulate){

    this.setCurrentItemInternal(newCurrItem,false,true);

     this.requestLayout();

 }

6.根据mFirstLayout判断是否执行this.populate(item);(mFirstLayout = false)

总结:所以这里有3种情况:

1.   needPopulate= false  &&  newPos == -1   -------> (表现为ui不更改)

2.  needPopulate= true  &&  newPos == -1   -------> (表现为ui不更改)

3.  needPopulate= true  &&  newPos == -2   -------> (表现为ui根据adapter提供的实例修改)

情况1:不需要调用

情况2:调用了populate,但是需要的iteminfo都存在所以不会调用addnewitem,导致如果集合中相同位置的引用改变了。使用的还是mItems缓存的旧的对象,假如mitems中的每一个对象都有remove的机会那么视图在拖动中总有机会去更新到最新的。

情况3:清空了mItems,导致每一项重新开始调用addnewitem和this.mAdapter.instantiateItem(this, position)。

2.删:

 和改一样有3种情况

1.   needPopulate= false  &&  newPos == -1   -------> ui无修改

2.  needPopulate= true  &&  newPos == -1     -------> ui展现正确的当前页

3.  needPopulate= true  &&  newPos == -2    ------->(表现为ui根据adapter提供的实例修改)

注:1.其中情况2假如是从不正确的当前页修改为正确的当前页,他还是可以拖动到后   一页应为 mItems 并没有清除之前的iteminfo所以在ontouch#case2的performdrag中rightBound 计算 还是按照之前的方法计算然后调用scrollTo 去滚动。但是ontouch#case1:this.setCurrentItemInternal(nextPage,true,true, initialVelocity)------>else if (item >=this.mAdapter.getCount()) {

item =this.mAdapter.getCount() -1;

}和 this.scrollToItem(item, smoothScroll, velocity, dispatchSelected);

  又给他设置到正确的位置了,然后ui就是 可以拖到最后一页但是就是翻不过去;

    2.和情况2类似,情况一假如翻到最后一页,然后调用notifyDataSetChanged没有反应,但是在你收触摸到屏幕,不管是什么方向的去触发performdarg 他最后都会返回到正确的最后一页。

讨论:needPopulate 值在删情况下变动:

  mOffscreenPageLimit 为1:

  adapter 的数据长度改动            当前页 (从1开始)             needPopulate值

    1-----0                                          1                                              false

    2-----1                                          1                                               false     

   2-----1                                            2                                             false    

   3-----2                                            1                                            false     

   3-----2                                            2                                           false     

   3-----2                                            3                                            false     

   4-----3                                            1                                            true     

   4-----3                                              2                                          false  

  4-----3                                               3                                         false  

  4-----3                                               4                                          true 

所以得出 也不是在删数据的时候都会去设置正确的当前页面。比如在3-2,和4-3的ui变动是不一样的,这是由needPopulate值决定的。



三:记录完了。over

你可能感兴趣的:(PagerAdapter 数据的增删改)