简体   繁体   English

Android:Paging3 使用 cloud-firestore 创建远程中介

[英]Android: Paging3 create remotemediator with cloud-firestore

I am trying to create a RemoteMediator with Paging3, where I cache my local results in order to save network traffic, cloud-firestore document access and to count the amount of items per query, to show placeholders.我正在尝试使用 Paging3 创建一个 RemoteMediator,我在其中缓存本地结果以节省网络流量、云火存储文档访问并计算每个查询的项目数量以显示占位符。

I've already successfully implemented the "only network way" by implementing a pagingsource that access my cloud-firestore and loads the nextpage.我已经通过实现访问我的 cloud-firestore 并加载下一页的分页源成功地实现了“唯一的网络方式”。 But I am struggling with the RemoteMediator way, because there are zero tutorials how to do this in combination with cloud-firestore.但我正在努力使用 RemoteMediator 方式,因为如何结合 cloud-firestore 做到这一点的教程为零。

I will provide my current approach (pagingSource way) and how far I got with my RemoteMediator.我将提供我当前的方法(pagingSource 方式)以及我的 RemoteMediator 走了多远。 I appreciate any help.我很感激任何帮助。

Repository存储库

@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()
}

Current Approach (working)当前方法(工作)

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 approach (no clue) 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
        )
    }

}

There's many problems with your implementation, first of all, repository shouldn't be injected into data source, it should be backward and create an injected instance of the dataSource into repository with a function that provides data from dataSource with proper configuration, the correct flow involves to pull paginated data from dataSource who pulls the data from database, then when data is over, the dataSource should ask for more data to the remoteMediator, who is in charge of refresh, append or preppend data from a network source based on the type of request the dataSource is asking for, finally your repository should be injected into useCases for each function that provides de data (flow, liveData RxJava, an so...) to the UI and work with it in a recyclerView or lazyColumn(If you're using compose).您的实现存在很多问题,首先,存储库不应该注入数据源,它应该是向后的,并使用 function 将数据源的注入实例创建到存储库中,该 function 提供来自具有正确配置的数据源的数据,正确的流程涉及到从dataSource拉分页数据,从dataSource拉取数据,当数据结束时,dataSource应该向remoteMediator请求更多数据,remoteMediator负责刷新,append或根据类型从网络源中添加数据数据源请求的请求,最后你的存储库应该被注入到每个 function 的用例中,这些 function 向 UI 提供数据(流,liveData RxJava,等等......)并在 recyclerView 或lazyColumn 中使用它(如果你'正在使用撰写)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 cloud-firestore 中的集合接收所有文档对象? - How can I receive all document objects from a collection in cloud-firestore? Android 中的云 Firestore 的离线持久性 - Offline persistance with cloud firestore in Android Flutter:Android 中的 Cloud Firestore (24.2.2) 内部错误 - Flutter: Internal error in Cloud Firestore (24.2.2) in Android 如何在 Cloud firestore 中动态创建新集合? - How to create new collection in Cloud firestore dynamically? Android:Cloud Firestore (24.0.2) 中的内部错误 - Android: Internal error in Cloud Firestore (24.0.2) 使用 Cloud Firestore 数据库 API 创建云 Firestore 数据库,其中“database_id”为“(默认)”不起作用 - using Cloud Firestore Database API to create cloud firestore database with`database_id` of '(default)' not working 云功能:尝试从云功能“部署失败”在 Firestore 上创建用户 - cloud functions: trying to create user on firestore from cloud functions "failed to deploy" 将 Cloud Firestore 数据预先写入 android kotlin 中的纯文本 - Pre-written Cloud Firestore data into plain text in android kotlin 2 个日期(时间戳)之间的差异 Android Studio 和 Cloud Firestore - Difference between 2 dates ( timestamps ) Android Studio and Cloud Firestore Cloud Firestore 或查询 - Cloud Firestore OR query
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM