検索されたアイテムのリストを表示する検索フラグメントがあります。ユーザーが何かを入力すると、その文字列を新しいクエリ パラメータとして url に渡し、ページング 3 ライブラリを使用して新しいリストを取得します。
最初の解決策は次のとおりです。
//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)
}
}
}
url ( を変更することによるこのソリューションではshowPostList(newUrl)
、リストは変更されずに残ります。おそらく、viewModel でキャッシュされたリストを使用します。
別の解決策はshowPostList(initUrl)
、 in onViewCreated
of fragment を使用してから、パラメーターを変更してblewメソッドを使用することです。
//fragment
fun changePostList(url: String) {
viewModel.postListUrl = url
postListAdapter.refresh()
}
これは機能しますが、古いリストと新しいリストに共通のアイテムがある場合、新しいリストは最後の共通の表示アイテムに表示されます。たとえば、古いリストの 5 番目の項目が新しいリストの 7 番目と同じ場合、リストを変更して新しいリストを表示すると、最初の項目ではなく 7 番目の項目から開始されます。
ここで別の解決策を見つけました:
//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)
}
}
}
ただし、このリストを使用すると、フラグメントに戻って更新され、Recyclerview
状態が変化することがあります。