简体   繁体   中英

How to transform PagingData<T> into model in collectLatest() in UI

I am having a situation, where once I get pagingData <T: UIModel> , I need to get additional data from a different API. The second Api requires arguments that are there in first API response. Currently I am collecting in UI Layer in lifecyclescope as,

            loadResults().collectLatest {

                PagingResultAdapter.submitData(lifecycle, it)
               
                // Extracting the data inside PagingData and setting in viewmodel.
                it.map { uiModel -> 
                    Timber.e("Getting data inside map function..")
                    viewModel.setFinalResults(uiModel)
                }
            }
        }

But the problem is, the map{} function on pagingData won't run during data fetching . List is populated, ui is showing the items in recyclerview. But the map function not running..(I am not able see the log)

The UI layer loadResults() function in-turn calls the viewmodel.loadResults() with UI level variables. In terms of paging everything is working fine, but I cannot transform the pagingdata into UIModel in any layer. Official site suggests to use map{} function only.

https://developer.android.com/topic/libraries/architecture/paging/v3-transform#basic-transformations

B ut I am not getting at which layer I should apply map{} and also before collecting or after collecting..Any help is good..

PagingData.map is a lazy transformation that runs during collection when you call .submitData(pagingData) . Since you are only submitting the original un-transformed PagingData your .map transform will never run.

You should apply the .map to the PagingData you will actually end up submitting in order to have it run. Usually this is done from the ViewModel , so that the results are also cached in case you end up in a config change or cached scenario like when navigating between fragments.

You didn't share your ViewModel / place you are creating your Pager, but assuming this happens at a different layer you would have something like:

MyViewModel.kt

fun loadResults() = Pager(...) { ... }
  .flow
  .map {
    Timber.e("Getting data inside map function..")
    setFinalResults(uiModel)
    it
  }
  .cachedIn(viewModelScope)

MyUi.kt

viewModel.loadResults().collectLatest {
  pagingDataAdapter.submitData(it)
}

NOTE: You should use the suspending version of .submitData since you are using Flow / Coroutines, because it is able to propagate cancellation direction instead of relying on launched job + eager cancellation via the non-suspending version. There shouldn't be any visible impact, but it is more performant.

Try with:

import androidx.paging.map

.flow.map { item ->    
    item.map { it.yourTransformation() }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM