最近开了一个新项目,使用的是Google 2018 IO大会 推荐的新的app架构,以下: android
这里主要讲Paging + Room遇到的问题:
基础的参考官方样例: github.com/googlesampl…
git
PagedList的DataSource.Factory: github
为何PagedList里的其余数据是null,能不能把null去除
尝试一、发现PagedList的Config中有enablePlaceholders(支持占位)属性,默认为true,支持null,能不能改成false,这样PagedList中就不会有null 数据库
只能往Room的源码挖了,为何会返回null:
一、将Room与PagedList联系起来的是新建PagedList传入的Room产生的DataSource.Factory bash
三、Debug后发现,Cursor的长度与PagedList的Observer接收到的数据长度一致,因此由表入里,看看这个方法的上游是哪,为何cursor中会有null的数据 架构
LimitOffsetDataSource.loadRange() app
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.requestedLoadSizeide
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的 ui
五、查找params.requestedLoadSize的由来
PositionalDataSource.dispatchLoadInitial(),来源于该方法的参数,仍是得往上寻找:
初始化PagedList时,将initialLoadSizeHint属性设置的足够大: