持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
为了活动小家电,接着上篇搞!
方案四
分别创建单个状态数据类,Loading和Error
ViewModel
@HiltViewModel
class ProgramFourViewModel @Inject constructor(
private val repository: LibraryRepository
) : ViewModel() {
data class State(
val name: String = "",
val price: String = ""
) {
val isEmpty: Boolean = name.isEmpty() && price.isEmpty()
}
private val _state: MutableStateFlow<State> = MutableStateFlow(State())
val state: StateFlow<State> = _state.asStateFlow()
private val _loading: MutableStateFlow<Boolean> = MutableStateFlow(false)
val loading: StateFlow<Boolean> = _loading.asStateFlow()
private val _error: MutableStateFlow<Boolean> = MutableStateFlow(false)
val error: StateFlow<Boolean> = _error.asStateFlow()
init {
viewModelScope.launch {
_loading.value = true
val response = repository.getBookInfo()
response
.onSuccess { bookInfo ->
_loading.value = false
_state.update { state ->
state.copy(
name = bookInfo.name,
price = bookInfo.price
)
}
}
.onFailure {
_loading.value = false
_error.value = true
}
}
}
}
Activity
@AndroidEntryPoint
class ProgramFourActivity : BindActivity() {
private val viewModel: ProgramFourViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 书本信息展示
lifecycleScope.launch {
viewModel.state.collect { state ->
binding.tvName.text = state.name
binding.tvPrice.text = state.price
}
}
// 加载异常展示
lifecycleScope.launch {
viewModel.error.collect { error ->
binding.ivError.isVisible = error
}
}
// 加载中展示
lifecycleScope.launch {
viewModel.loading.collect { loading ->
binding.ivLoading.isVisible = loading
}
}
}
}
优点
- UI 状态不依赖于加载或错误,因此可以单独处理。
- 使用 Base 时,它提供了可扩展的结构。
- 通过单独定义状态,可以更好的更改所需的数据。
缺点
- 如果 UI 状态依赖于加载或错误,则处理有些复杂。
- 因为加载状态可以在几个地方改变,所以你需要小心改变状态。
- 处理订阅的代码很多,而且很复杂。
使用场景
- 将 UI 状态与加载和错误分开使用时
- 如果您想在 Base 中处理一般的加载和错误
总结
你会使用什么 UI 策略?是否会从中选择一种方案呢?\
最后,考虑到团队成员的问题和约定,我认为这个问题没有完美的答案,团队实践比最佳实践更重要。但是我们需要根据自身研发的业务场景去选择一种更合适的方案,目的就是方便后期的扩展与维护。
我的问题
那么如何处理最近使用 LiveData 或 StateFlow 的状态?这是一个困扰许久的问题,有这样的需求我们一直都是用保存状态的形式做处理,但是始终觉得不太优雅。