我正在尝试使用 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)
}
}
}
RemoteMediator 方法(没有线索)
@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
)
}
}