内容简介:最近开了一个新项目,使用的是Google 2018 IO大会 推荐的新的app架构,如下:这里主要讲Paging + Room遇到的问题:基础的参考官方样例:
最近开了一个新项目,使用的是Google 2018 IO大会 推荐的新的app架构,如下:
官方地址这里主要讲Paging + Room遇到的问题:
基础的参考官方样例: github.com/googlesampl…
PagedList的创建:
完全照搬官方的样例,传入自定义的BoundaryCallBack:
PagedList的DataSource.Factory:
实现交由子类:
Dao:
OK,到这里,基本上都是照搬的官方的样例了,接下来就看运行结果了:
数据能正确获取,并正确刷UI。但是,当数据超过30条(后面交代为什么是30)时,具体效果如下:
PagedList的长度为50,但是只有30item是有数据的,其他都用null来占位了,
这会造成一个问题,当我需要删除一条数据时,删除后刷新UI,adapter的getItem()方法是会返回null,而我之所以用Paging + Room的形式,就是为了删除,因为PagedList不支持删除,233333。痛哭流涕啊。。。。。。。。解题思路:
为什么PagedList里的其他数据是null,能不能把null去除
尝试一、发现PagedList的Config中有enablePlaceholders(支持占位)属性,默认为true,支持null,能不能改为false,这样PagedList中就不会有null
解决方案:结果:
设置PagedList的配置enablePlaceholders为false后,PagedList的Observer接收到的数据并不完整,等于是PagedList将null数据过滤了。
只能往Room的源码挖了,为什么会返回null:
1、将Room与PagedList联系起来的是新建PagedList传入的Room产生的DataSource.Factory
2、寻找具体的DataSource
从FavorVideoDao的具体实现类中,可以看出,getAll()方法返回的是LimitOffsetDataSource,而其中只有恰巧只有一个返回集合为List< Object>的方法,参数为Cursor,所以应该能断定是从数据库中查出数据后处理返回给PagedList的方法。
3、Debug后发现,Cursor的长度与PagedList的Observer接收到的数据长度一致,所以由表入里,看看这个方法的上游是哪,为什么cursor中会有null的数据
LimitOffsetDataSource.loadRange()
从这个方法,我们能发现Cursor的由来,mDb.query(sqLiteQuery);,Sqlite语句sqLiteQuery的由来就有意思了,
limit ? offset ? ,查询多少个,偏移多少(从第几个开始),到这里其实就有点眉目了
而这两个值其实来自与方法的参数:
4、查找limit和offset的由来 LimitOffsetDataSource.loadInitial():
PositionalDataSource.computeInitialLoadPosition(): offset:
public static int computeInitialLoadPosition(@NonNull LoadInitialParams params, int totalCount) { int position = params.requestedStartPosition; int initialLoadSize = params.requestedLoadSize; int pageSize = params.pageSize; int roundedPageStart = Math.round(position / pageSize) * pageSize; // 这里肯定是大于0的 // maximum start pos is that which will encompass end of list int maximumLoadPage = ((totalCount - initialLoadSize + pageSize - 1) / pageSize) * pageSize; // 所以必须保证maximumLoadPage小于等于0,所以必须保证 initialLoadSize必须足够大 roundedPageStart = Math.min(maximumLoadPage, roundedPageStart); // minimum start position is 0 roundedPageStart = Math.max(0, roundedPageStart); // 所以,roundedPageStart必须小于等于0 return roundedPageStart; } 复制代码
如果想要将所有数据都加载出来,offset必须的保证为0,具体看上面代码注释,所以关键在于params.requestedLoadSize
PositionalDataSource.computeInitialLoadSize(): limit:
public static int computeInitialLoadSize(@NonNull LoadInitialParams params, int initialLoadPosition, int totalCount) { return Math.min(totalCount - initialLoadPosition, params.requestedLoadSize); // 总的个数减去加载的起始位置 params.requestedLoadSize 两数去最小值,为加载的总个数 } 复制代码
所以当params.requestedLoadSize足够大时,数据库中的所有数据都会被取出
Room加上limit逻辑,也是为了效率更高,但是因为有删除的业务需求,导致异常,所以还是每次全部都取出,RecyclerView刷新时,页只会刷新可见的Item,所以性能上还是OK的5、查找params.requestedLoadSize的由来
PositionalDataSource.dispatchLoadInitial(),来源于该方法的参数,还是得往上寻找:
TiledPagedList的构造方法:
来源于Config的initialLoadSizeHint属性,所以最后回到了PagedList的Config的initialLoadSizeHint属性。此处正好回答前面为什么只保存30个数据了:当未设置Config的initialLoadSizeHint属性时,默认为PageSize的3倍。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- NULL 指针、零指针、野指针
- Swift iOS : 上拉刷新或者下拉刷新
- Swift iOS : 上拉刷新或者下拉刷新
- 将数组和矩阵传递给函数,作为C中指针的指针和指针
- C语言指针数组和数组指针
- python(函数指针和类函数指针)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。