我有密封类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>> -> {}
您无法使用
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>
}