Hadi Ahmadi
Hadi Ahmadi

Reputation: 1992

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

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.

Upvotes: 10

Views: 4955

Answers (1)

Rajat Negi
Rajat Negi

Reputation: 89

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 .

Upvotes: 6

Related Questions