【问题标题】:Android: Paging3 create remotemediator with cloud-firestoreAndroid:Paging3 使用 cloud-firestore 创建远程中介
【发布时间】:2021-01-06 15:58:24
【问题描述】:

我正在尝试使用 Paging3 创建一个 RemoteMediator,我在其中缓存我的本地结果,以节省网络流量、cloud-firestore 文档访问并计算每个查询的项目数量,以显示占位符。

我已经通过实现访问我的 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
        )
    }

}

【问题讨论】:

  • 我想你可能对这篇文章感兴趣,How to paginate Firestore using Paging 3 on Android?
  • @AlexMamo 不,这是不使用房间数据库作为本地缓存的常用方法。他使用 pagingsource 而不是 RemoteMediator。如上所述,我已经知道如何做到这一点。

标签: android kotlin google-cloud-firestore android-paging android-paging-3


【解决方案1】:

你的实现有很多问题,首先,存储库不应该注入数据源,它应该是向后的,并创建一个注入数据源的实例到存储库中,并使用一个函数从 dataSource 提供具有适当配置的数据,正确的流程包括从 dataSource 中提取分页数据,从数据库中提取数据,然后当数据结束时,dataSource 应该向 remoteMediator 请求更多数据,remoteMediator 负责从基于网络的源中刷新、附加或附加数据根据 dataSource 请求的请求类型,最后应该将您的存储库注入到每个向 UI 提供数据(流、liveData RxJava 等...)的函数的 useCases 中,并在 recyclerView 或lazyColumn 中使用它(如果您使用的是撰写)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2019-03-28
    • 1970-01-01
    • 2021-03-24
    • 2018-07-11
    • 2018-05-31
    • 2023-04-01
    相关资源
    最近更新 更多