Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
231 views
in Technique[技术] by (71.8m points)

kotlin - 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.

I've already successfully implemented the "only network way" by implementing a pagingsource that access my cloud-firestore and loads the nextpage. But I am struggling with the RemoteMediator way, because there are zero tutorials how to do this in combination with cloud-firestore.

I will provide my current approach (pagingSource way) and how far I got with my 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)

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

}
question from:https://stackoverflow.com/questions/65599077/android-paging3-create-remotemediator-with-cloud-firestore

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...