最近開了一個新項目,使用的是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屬性設置的足夠大: