3

我正在研究新的 Android Room Paging 库

   implementation "androidx.paging:paging-runtime-ktx:3.0.0-alpha09"

我的源数据库表大约有 10,000 行,我按名称字段的第一个字符进行过滤,如下所示:-

@Query("SELECT * from citation_style WHERE citation_style_name LIKE :startsWith ORDER BY citation_style_name ASC")
fun fetch(startsWith: String): PagingSource<Int, CitationStyleDO>

存储库

fun fetch(startsWith: String): Flow<PagingData<CitationStyleDO>> {
    return Pager(
        PagingConfig(pageSize = 60, prefetchDistance = 30, enablePlaceholders = false, maxSize = 200)
    ) { database.citationStyleDao().fetch("$startsWith%") }.flow
}

视图模型

fun fetch(startsWith: String): Flow<PagingData<CitationStyleDO>> {
    return repository.fetch(startsWith).cachedIn(viewModelScope)
}

分段

override fun onStartsWithClicked(startsWith: String) {
    lifecycleScope.launch {
        viewModel.fetch(startsWith).collectLatest { adapter.submitData(it) }
    }
}

这是lifecycleScope.launch {...}每次更改 Starts With 字符时重复使用的正确方法吗?

我应该被map{}switchMap{}MutabaleLiveData<String>for StartwWith 触发吗?

4

1 回答 1

5

这是行不通的,因为 submitData 在PagingData失效之前不会返回。您可能会遇到竞争场景,其中您启动了多个作业,PagingDataAdapter并试图从多个PagingData.

更“流”的方式是将您的 fetch 调用转换为流并将其与您的 结合起来Flow<PagingData>,这将在每次查询更改时自动传播取消。

其他几件事:

建议让 Paging 为您进行过滤,因为这样您可以避免每次搜索更改时从 DB 重新获取,并且您可以依靠 Paging 来处理配置更改和恢复状态。

您应该使用viewLifecycleOwner而不是lifecycleScope直接使用,因为您不希望在片段的视图被破坏后进行分页工作

例如,

视图模型

val queryFlow = MutableStateFlow("init_query")
val pagingDataFlow = Pager(...) {
        dao.pagingSource()
    }.flow
    // This multicasts, to prevent combine from refetching
    .cachedIn(viewModelScope)
    .combine(queryFlow) { pagingData, query -> 
        pagingData.filter { it.startsWith(query)
    }
    // Optionally call .cachedIn() here a second time to cache the filtered results. 

分段

override fun onStartsWithClicked(startsWith: String) {
    viewModel.queryFlow = startsWith
}

override fun onViewCreated(...) {
     viewLifecycleOwner.lifecycleScope.launch {
viewModel.pagingDataFlow.collectLatest { adapter.submitData(it) }
}

注意:如果需要,您绝对可以使用 Room 进行过滤,这可能是.flatMapLatest在 queryFlow 上的正确方法并返回一个新的Pager每个尖,并将查询项传递给返回一个PagingSource

视图模型

queryFlow.flatMapLatest { query ->
    Pager(...) { dao.pagingSource(query) }
        .cachedIn(...)
}
于 2020-12-06T18:16:52.523 回答