-1

I am creating an app in which i am using RxJava and paging 3 library. I am using RxPagingSource and Retrofit to paginate response coming from Server but i have to fetch some data from Firestore and have to paginate

override fun loadSingle(params: LoadParams<QuerySnapshot>): Single<LoadResult<QuerySnapshot, Notification>> {
        var currentPage : QuerySnapshot
        if(params.key != null){
            currentPage = params.key!!
        }else{
            reference
                .limit(10)
                .get()
                .addOnCompleteListener(OnCompleteListener {
                    if(it.isSuccessful){
                        currentPage = it.result
                        val lastDocumentSnapshot = it.result.documents[it.result.size() - 1]
                        reference
                            .limit(10)
                            .startAfter(lastDocumentSnapshot)
                            .get()
                            .addOnCompleteListener(OnCompleteListener {
                                val nextPage: QuerySnapshot
                                if(it.isSuccessful){
                                    nextPage = it.result
                                    return Single.just(
                                        LoadResult.Page(
                                            data = currentPage.toObjects(Notification::class.java),
                                            prevKey = null,
                                            nextKey = nextPage
                                        )
                                    )
                                    //return
                                }
                            })
                    }
                })
        }

This is code i tried but its not working for me, there is many mistake in this code

How can i paginate Firestore data using RxPagingSource provided by Paging 3 library

  • 1
    "it's not working" doesn't provide enough information so we can help. What exactly in this code doesn't work the way you expect? Tell us what is wrong with shared code. Do you have any errors? – Alex Mamo Jul 21 '21 at 12:56
  • @AlexMamo i followed https://medium.com/@ericampire/firestore-pagination-with-paging-3-762e371cc57f this which is use to paginate by coroutine i modify code given to this link to RxPagingSource but i failed – imran khan Jul 21 '21 at 13:12
  • You might also be interested in this article, [How to paginate Firestore using Paging 3 on Android?](https://medium.com/firebase-tips-tricks/how-to-paginate-firestore-using-paging-3-on-android-c485acb0a2df). It's not with RxJava, but I think you might get the idea. – Alex Mamo Jul 21 '21 at 13:17
  • @AlexMamo i know how to paginate Firestore using Paging3 with coroutine , but want it with Rx. – imran khan Jul 24 '21 at 16:32

1 Answers1

0

PagingDataSource.kt

class NotificationPagingDataSource(val service: AppRepository) :
    RxPagingSource<Int, Notification>() {

    override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, Notification>> {

        val page = params.key ?: 1
        return service.getFireNotification(page)
            .subscribeOn(Schedulers.io())
            .map {
                toLoadResult(it, page)
            }
            .onErrorReturn {
                LoadResult.Error(it)
            }
    }


    private fun toLoadResult(
        data: QuerySnapshot,
        page: Int
    ): LoadResult<Int, Notification> {
     
        Log.i("TAG"," mappingstarted:::  3")
        return LoadResult.Page(
            data = data.toObjects(Notification::class.java),
            prevKey = if (page <= 1) null else page - 1,
            nextKey = if (data.size() == 0) null else page + 1
        )
    }


    override fun getRefreshKey(state: PagingState<Int, Notification>): Int? {
        return state.anchorPosition
    }


}

AppRepository.kt

 var timestamp : String? = null

fun getFireNotification(i: Int): Single<QuerySnapshot> {


        return Single.create<QuerySnapshot>(SingleOnSubscribe { emitter ->

            if (i == 1) {
                FirebaseFirestore.getInstance()
                    .collection(Constant.NOTIFICATION_NODE).document(FirebaseAuth.getInstance().currentUser.uid)
                    .collection(Constant.USER_NOTIFICATION_NODE)
                    .limit(15)
                    .get()
                    .addOnCompleteListener {
                        if (it.isSuccessful) {
                            emitter.onSuccess(it.result)
                            timestamp = it.result.documents.last().data?.get("timestamp").toString()
                        }
                    }
                    .addOnFailureListener {
                        Log.i("TAG"," addOnFailureListener:: $it")
                    }
            } else {
                FirebaseFirestore.getInstance()
                    .collection(Constant.NOTIFICATION_NODE).document(FirebaseAuth.getInstance().currentUser.uid)
                    .collection(Constant.USER_NOTIFICATION_NODE)
                    .orderBy("timestamp",Query.Direction.DESCENDING)
                    .startAfter(timestamp)
                    .limit(15)
                    .get()
                    .addOnCompleteListener {
                        if (it.isSuccessful) {
                            if(it.result.documents.isNotEmpty()) {
                                emitter.onSuccess(it.result)
                                timestamp = it.result.documents.last().data?.get("timestamp").toString()
                            }
                        }
                    }
                    .addOnFailureListener {
                    }
            }
        })
    }

FirebaseViewModel.kt

private val notificationPagingdata: MediatorLiveData<PagingData<NotificationModal>> =
        MediatorLiveData()

    fun getNotification(){
         disposable.add(Pager(
            config =  PagingConfig(
                pageSize = 15,
                enablePlaceholders = false,
                prefetchDistance = 1,
            ),
            pagingSourceFactory = {
                NotificationPagingDataSource(repository)
            }
        ).flowable.subscribe({
           notificationPagingdata.value  = it
           }
       )
     )
}

 fun observeNotificationPagingDataSource():LiveData<PagingData<NotificationModal>>{
        return notificationPagingdata
    }

YourFragment or Activity.kt

private fun setObserver() {
        fireViewModel.observeNotificationPagingDataSource().observe(viewLifecycleOwner, Observer {
            adapter.submitData(lifecycle,it)
        })
    }