Android Paging 3 library: how to change list with new param?
Asked Answered
V

1

10

I have a search fragment that shows list of searched items. if user type something, I pass that string to url as new query parameter and get new list using paging 3 library.

first solution is:

//viewModel
lateinit var postListUrl: String

    val postList: Flow<PagingData<Post>> = Pager(PagingConfig(pageSize = 20)) {
        PostPagingSource(postRepository, postListUrl)
    }.flow.cachedIn(viewModelScope)

//fragment
fun showPostList(url: String) {
        postListAdapter.submitData(lifecycle, PagingData.empty())
        viewModel.postListUrl = url
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.postList.collectLatest {
                postListAdapter.submitData(it)
            }
        }
    }

by this solution by changing url (showPostList(newUrl), list remain without any changes. maybe using cached list in viewModel.

another solution is: using showPostList(initUrl) in onViewCreated of fragment and then using blew method by changing parameter:

//fragment
fun changePostList(url: String) {
        viewModel.postListUrl = url
        postListAdapter.refresh()
    }

this work but if old list and new list have common item, new list show on last common visible item. for example if 5th position item of old list is same as 7th of new list, then on after list change to show new list, it start from 7th position not first item.

I found another solution here:

//viewModel
val postListUrlFlow = MutableStateFlow("")
    val postList = postListUrlFlow.flatMapLatest { query ->
        Pager(PagingConfig(pageSize = 20)) {
            PostPagingSource(postRepository, query)
        }.flow.cachedIn(viewModelScope)
    }

//fragment
fun showPostList(url: String) {
        postListAdapter.submitData(lifecycle, PagingData.empty())
        viewModel.postListUrlFlow.value = url
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.postList.collectLatest {
                postListAdapter.submitData(it)
            }
        }
    }

but by using this list refresh on back to fragment and sometimes Recyclerview state changing.

Vere answered 9/1, 2021 at 14:11 Comment(7)
What do you mean by RecyclerView state changing? When you say navigating back to your fragment refreshes the list, are you sure its not a result of you calling showPostList?Hoop
@Hoop I call showPostList in onViewCreated. in other fragments, calling this method does not refresh list because of cached in view model. But by using MutableStateFlow cached in does not work.Vere
@Hoop It's seems By changing URL and calling adapter.refresh (second solution) problem is not exist if I can disable diffUtill in this moment. is there a way to do that?Vere
There is no way to prevent DiffUtil on refresh, but what you can do is clear the list first using PagingData.empty().Hoop
Something like this perhaps: ``` val postListUrlFlow = MutableStateFlow("") val postList = postListUrlFlow.flatMapLatest { query -> Pager(PagingConfig(pageSize = 20)) { PostPagingSource(postRepository, query) }.flow .onStart { emit(PagingData.empty()) } .cachedIn(viewModelScope) } ```Hoop
@Hoop using PagingData.empty() does not solve the problem.Vere
Fixed it: i needed to fix my comparisions. See https://mcmap.net/q/643903/-pagedlistadapter-jumps-to-beginning-of-the-list-on-receiving-new-pagedlistDeneendenegation
B
6
class MyViewModel:ViewModel(){
  private val _currentQuery = MutableLiveData<String>()
  val currentQuery:LiveData<String> = _currentQuery


  val users = _currentQuery.switchMap { query->
      Pager(PagingConfig(pageSize = 20)) {
      PostPagingSource(postRepository, query)
  }.livedata.cachedIn(viewModelScope)

  }


  fun setCurrentQuery(query: String){
       _currentQuery.postValue(query)
  }
}

By the use of

SwitchMap

you can get new results every time query is chnaged and it will replace the old data .

Bainter answered 22/1, 2022 at 11:17 Comment(2)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Conlin
this is a non-answer, there are so few details. Could you edit your response rajat negiEffieeffigy

© 2022 - 2024 — McMap. All rights reserved.