[英]How can I receive all document objects from a collection in cloud-firestore?
[英]Android: Paging3 create remotemediator with cloud-firestore
我正在嘗試使用 Paging3 創建一個 RemoteMediator,我在其中緩存本地結果以節省網絡流量、雲火存儲文檔訪問並計算每個查詢的項目數量以顯示占位符。
我已經通過實現訪問我的 cloud-firestore 並加載下一頁的分頁源成功地實現了“唯一的網絡方式”。 但我正在努力使用 RemoteMediator 方式,因為如何結合 cloud-firestore 做到這一點的教程為零。
我將提供我當前的方法(pagingSource 方式)以及我的 RemoteMediator 走了多遠。 我很感激任何幫助。
@Singleton
class ShopPagingRepositoryImpl @Inject constructor(private val db: FirebaseFirestore) : ShopPagingRepository {
override suspend fun getCurrentPage(query: QueryHolder): QuerySnapshot = db.collection(FIREBASE_PRODUCTS_BASE_PATH)
.limit(SHOP_DB_DOCUMENT_LIMIT)
.whereEqualTo(FIREBASE_PRODUCT_CATEGORY, query.category)
.orderBy(query.order)
.get()
.await()
override suspend fun getNextPage(lastDocument: DocumentSnapshot, query: QueryHolder): QuerySnapshot = db.collection(FIREBASE_PRODUCTS_BASE_PATH)
.limit(SHOP_DB_DOCUMENT_LIMIT)
.orderBy(query.order, query.direction)
.startAfter(lastDocument)
.whereEqualTo(FIREBASE_PRODUCT_CATEGORY, query.category)
.get()
.await()
}
class ShopPagingSource(
private val shopRepository: ShopPagingRepository,
private val query: QueryHolder
) : PagingSource<QuerySnapshot, Product>() {
private companion object {
const val SHOP_MAX_LOADING_TIME: Long = 5000L
}
override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, Product> {
return try {
withTimeout(SHOP_MAX_LOADING_TIME) {
val currentPage = params.key ?: shopRepository.getCurrentPage(query)
val nextPage: QuerySnapshot? = if (currentPage.size() != 0) {
val lastDocumentSnapShot = currentPage.documents[currentPage.size() - 1]
shopRepository.getNextPage(lastDocumentSnapShot, query)
} else null
LoadResult.Page(
data = currentPage.toObjects(),
prevKey = null,
nextKey = nextPage
)
}
} catch (e: Exception) {
Timber.e("Mediator failed, Unknown Error: ${e.message.toString()}")
LoadResult.Error(e)
}
}
}
@ExperimentalPagingApi
class ShopPageMediator(
private val shopRepository: ShopPagingRepository,
private val query: QueryHolder,
private val shopDB: ShopDatabase
): RemoteMediator<QuerySnapshot, Product>() {
private val shopDAO = shopDB.shopDao()
override suspend fun load(
loadType: LoadType,
state: PagingState<QuerySnapshot, Product>,
): MediatorResult {
val loadKey = when(loadType) {
LoadType.REFRESH -> null
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> {
val lastItem = state.lastItemOrNull() ?: return MediatorResult.Success(endOfPaginationReached = true)
// why lastitem.id, here my lastitem is product. Does this indicate the end of the page?
lastItem.id
}
}
val currentPage = shopRepository.getCurrentPage(
query
)
shopDB.withTransaction {
if (loadType == LoadType.PREPEND) {
// TODO(shopDAO.deleteByQuery(query))
}
shopDAO.insertAll(currentPage.toObjects())
}
val nextPage: QuerySnapshot? = if (currentPage.size() != 0) {
val lastDocumentSnapShot = currentPage.documents[currentPage.size() - 1]
shopRepository.getNextPage(lastDocumentSnapShot, query)
} else null
// Didn't use the result of loadkey anywhere..
return MediatorResult.Success(
endOfPaginationReached = nextPage == null
)
}
}
您的實現存在很多問題,首先,存儲庫不應該注入數據源,它應該是向后的,並使用 function 將數據源的注入實例創建到存儲庫中,該 function 提供來自具有正確配置的數據源的數據,正確的流程涉及到從dataSource拉分頁數據,從dataSource拉取數據,當數據結束時,dataSource應該向remoteMediator請求更多數據,remoteMediator負責刷新,append或根據類型從網絡源中添加數據數據源請求的請求,最后你的存儲庫應該被注入到每個 function 的用例中,這些 function 向 UI 提供數據(流,liveData RxJava,等等......)並在 recyclerView 或lazyColumn 中使用它(如果你'正在使用撰寫)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.