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.
PagingData.empty()
. – Hoop