【问题标题】:Android Paging 3 library: how to change list with new param?Android Paging 3 库:如何使用新参数更改列表?
【发布时间】:2021-01-09 14:11:18
【问题描述】:

我有一个显示搜索项目列表的搜索片段。 如果用户输入内容,我将该字符串作为新的查询参数传递给 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 中使用缓存列表。

另一种解决方案是: 在片段的onViewCreated中使用showPostList(initUrl),然后通过更改参数使用自爆方法:

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

这项工作,但如果旧列表和新列表有共同项目,新列表显示在最后一个共同可见项目上。 例如,如果旧列表的第 5 位项目与新列表的第 7 位相同,则在列表更改以显示新列表后,它从第 7 位而不是第一项开始。

我找到了另一个解决方案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)
            }
        }
    }

但通过使用此列表刷新返回片段,有时Recyclerview 状态发生变化。

【问题讨论】:

  • RecyclerView 状态改变是什么意思?当您说导航回您的片段刷新列表时,您确定这不是您调用 showPostList 的结果吗?
  • @dlam 我在 onViewCreated 中调用 showPostList。在其他片段中,调用此方法不会刷新列表,因为缓存在视图模型中。但是使用缓存的 MutableStateFlow 是行不通的。
  • @dlam 似乎通过更改 URL 并调用 adapter.refresh (第二种解决方案)如果我现在可以禁用 diffUtill 问题就不存在了。有没有办法做到这一点?
  • 无法阻止 DiffUtil 刷新,但您可以先使用 PagingData.empty() 清除列表。
  • 可能是这样的:``` val postListUrlFlow = MutableStateFlow("") val postList = postListUrlFlow.flatMapLatest { query -> Pager(PagingConfig(pageSize = 20)) { PostPagingSource(postRepository, query) }.flow .onStart { emit(PagingData.empty()) } .cachedIn(viewModelScope) } ```

标签: android android-paging kotlin-flow android-paging-3


【解决方案1】:
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)
  }
}

使用

切换地图

每次更改查询时都可以获得新结果,它将替换旧数据。

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 2020-11-17
  • 1970-01-01
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-04
相关资源
最近更新 更多