kotlin 当我在第3页中重新提交数据时,UI加载状态未按预期运行

yr9zkbsy  于 2023-03-09  发布在  Kotlin
关注(0)|答案(1)|浏览(180)

在我的用户界面中,我有一个recyclerview和一个chip group。每个chip代表不同的调用来更新。当我点击一个chip时,我希望recyclerview会消失,直到加载新数据。RV确实消失了,但是当它再次显示时,它显示旧数据不到一秒钟,然后才改变为新数据。作为参考,我使用了paging codelab-〉www.example.comhttps://developer.android.com/codelabs/android-paging#0
我该怎么修呢?

碎片

我观察分页数据和负载状态如下:

viewLifecycleOwner.lifecycleScope.launch {
        pagingData.collectLatest(customAdapter::submitData)
    }

    viewLifecycleOwner.lifecycleScope.launch {
        customAdapter.loadStateFlow.collect { loadState ->
            header.loadState = loadState.mediator
                ?.refresh
                ?.takeIf { it is LoadState.Error && customAdapter.itemCount > 0 }
                ?: loadState.prepend

            val isListEmpty = loadState.refresh is LoadState.NotLoading && customAdapter.itemCount == 0
            emptyList.isVisible = isListEmpty
            recyclerView.isVisible = loadState.mediator?.refresh is LoadState.NotLoading ||  loadState.source.refresh is LoadState.NotLoading
            progressBar.isVisible = loadState.mediator?.refresh is LoadState.Loading
            retryButton.isVisible = loadState.mediator?.refresh is LoadState.Error && customAdapter.itemCount == 0
            val errorState = loadState.source.append as? LoadState.Error
                ?: loadState.source.prepend as? LoadState.Error
                ?: loadState.append as? LoadState.Error
                ?: loadState.prepend as? LoadState.Error
            errorState?.let {
                Toast.makeText(
                    requireContext(),
                    "\uD83D\uDE28 Wooops ${it.error}",
                    Toast.LENGTH_LONG
                ).show()
            }
        }
    }

下面是我如何更改类别:

chip1.setOnClickListener {
            viewLifecycleOwner.lifecycleScope.launch {
                onCategoryChanged(CustomAction.ChangeCategory(category = CustomCategory.A))
            }
        }
        chip2.setOnClickListener {
            viewLifecycleOwner.lifecycleScope.launch {
                customAdapter.refresh()
                onCategoryChanged(CustomAction.ChangeCategory(category = CustomCategory.B))
            }
        }

视图模型

下面是我如何根据视图模型中的状态类别更新分页数据:

val actionStateFlow = MutableSharedFlow<CustomAction>()
    val changedCategory = actionStateFlow
        .filterIsInstance<CustomAction.ChangeCategory>()
        .distinctUntilChanged()
        .onStart { emit(CustomAction.ChangeCategory(category = initialCategory)) }
    pagingDataFlow = state
        .flatMapLatest {
            when (it.category) {
                CustomCategory.A -> searchA(query = it.query)
                CustomCategory.B -> searchB(query = it.query)
            }
        }
        .cachedIn(viewModelScope)

private fun searchA(query: String): Flow<PagingData<CustomItem>> {
    return repository.getA(query = query).map { pagingData ->
        pagingData.map { it.mapToDomainModel() }
    }
}

private fun searchB(query: String): Flow<PagingData<CustomItem>> {
    return repository.getB(query = query).map { pagingData ->
        pagingData.map { it.mapToDomainModel() }
    }
}
7lrncoxx

7lrncoxx1#

我假设您使用的是RemoteMediator,这似乎是Paging3库的预期功能(尽管违反直觉)。
答案就在下面这段文档中:
RemoteMediator实现还可以覆盖initialize()方法,以检查缓存数据是否过期,并决定是否触发远程刷新。此方法在执行任何加载之前运行,因此您可以在触发任何本地或远程加载之前操作数据库(例如,清除旧数据)。
我自己做了它,使initialize()方法总是返回LAUNCH_INITIAL_REFRESH,我以为这将总是使寻呼机"从头开始",但似乎如果有东西缓存在数据库中,它仍然会显示该数据,然后触发刷新,这反过来应该清除数据库中的所有数据,并插入新的。

    • 溶液**:在RemoteMediatorinitialize()方法中,清除缓存项目的数据库。
    • 启发思考**:考虑一下你的用例。老实说,这是给你和我的建议:)如果你获取的数据依赖于查询参数,它需要缓存吗?对于一个离线优先的应用程序,你会缓存那些在应用程序/屏幕启动时就应该显示的数据。但是如果数据依赖于用户必须输入/选择的查询,那么只显示一个"无可用连接"错误应该是完全可以的。

相关问题