重构。使用 ViewModel 中的 MutableState 在 RecyclerView 中加载数据

问题描述 投票:0回答:1

我有密封类State,我需要将数据从

data class Loaded<T>
加载到Fragment中的RecyclerView。如何正确观察fragment中的状态并将其加载到RecyclerView中?主要问题是数据是通用的。

sealed class State {
    object Success : State()
    object Waiting : State()
    object Loading : State()
    data class Loaded<T>(val data: T) : State()
    class Error(val message: String) : State()
    class TokenError(val message: String) : State() 
}

我尝试使用此代码,它工作正常,但我收到警告 Uncheckedcast

val resorts = state.data as List<Resort>
roads as List<Route>

override fun initFlow(){
    viewLifecycleOwner.lifecycleScope.launch {
        viewModel.state.collect { state ->
            when (state) {
                State.Waiting -> {
                    binding.progressBar.isVisible = false
                }
                State.Loading -> {
                    binding.progressBar.isVisible = true
                }
                State.Success -> {
                    binding.progressBar.isVisible = false
                }

                is State.Loaded<*> -> {
                    if (state.data is List<*>
                        && state.data.all { item -> item is Resort }
                    ) {
                        val resorts = state.data as List<Resort>
                        addResortsOnMap(resorts)
                    }

                    if (state.data is List<*>
                        && state.data.all { item -> item is Route }
                    ) {
                        val roads = state.data
                        roadsAdapter.setData(roads as List<Route>)
                    }
                    binding.progressBar.isVisible = false
                }

                is State.Error -> {
                    binding.progressBar.isVisible = false
                    Toast.makeText(
                        requireContext(),
                        state.message,
                        Toast.LENGTH_SHORT
                    ).show()
                }

                is State.TokenError -> {
                    Toast.makeText(requireContext(), state.message, Toast.LENGTH_SHORT).show()
                    findNavController().navigate(R.id.login)
                }
            }
        }
    }
}

我也尝试签入when,但它没有编译我的应用程序。我收到错误:

Cannot check for instance of erased type:

is State.Loaded<List<Resort>> -> {}

android kotlin android-recyclerview kotlin-coroutines android-viewmodel
1个回答
0
投票

您无法使用

when
运算符检查类型,因为类型会在编译时被擦除并被
Any
替换。因此,在运行时,当
when
被执行时,类型不再是已知的。

如果你想摆脱“uncheckedcast”警告,你可以使用

as?
:

val resorts = state.data as? List<Resort>

但是在这种情况下,您应该处理转换过程中可能出现的失败,这将导致

resorts
被分配空值。

我的建议是重新考虑你的状态设计。

State
中的通用列表使架构变得复杂,因为您将被迫实现类型确定逻辑。我想您正在尝试重用一个视图来表示不同的数据类型,但是在您的应用程序流程中的某个时刻,您应该知道您想要呈现什么数据。

我要做的是定义两种不同的状态。

class ResortListState : State() {
    val data: List<Resort>
}

class RouteListState : State() {
    val data: List<Route>
}

© www.soinside.com 2019 - 2024. All rights reserved.