持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
为了活动小家电,接着上篇搞!
方案二
创建一个具有密封类的状态并创建与状态数量一样多的实现
ViewModel
@HiltViewModel
class ProgramTwoViewModel @Inject constructor(
private val repository: LibraryRepository
) : ViewModel() {
sealed class State {
data class Success(
val name: String,
val price: String
) : State()
object Empty : State()
object Failure : State()
object Loading : State()
}
private val _state: MutableStateFlow<State> = MutableStateFlow(State.Loading)
val state: StateFlow<State> = _state.asStateFlow()
init {
viewModelScope.launch {
_state.value = State.Loading
val response = repository.getBookInfo()
response
.onSuccess { bookInfo ->
val (name, price) = (bookInfo.name to bookInfo.price)
if (name.isEmpty() && price.isEmpty()) {
_state.value = State.Empty
} else {
_state.value = State.Success(bookInfo.name, bookInfo.price)
}
}
.onFailure {
_state.value = State.Failure
}
}
}
}
Activity
@AndroidEntryPoint
class ProgramTwoActivity : BindActivity() {
private val viewModel: ProgramTwoViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
viewModel.state.collect { state ->
// 加载中展示
binding.ivLoading.isVisible = state is State.Loading
// 加载异常展示
binding.ivError.isVisible = state is State.Failure
// 信息展示
if (state is State.Success) {
binding.tvName.text = state.name
binding.tvPrice.text = state.price
}
}
}
}
}
优点
- 通过实现类似于 MVI 的形式,可以清楚地表达 UI 的意图。
- 通过利用密封类,有利于面向对象的处理。
- 改变 UI 的代码没有分散相对比较集中,都是统一返回的,所以代码分析很方便。
- 由于它只有一种状态,因此没有必要考虑状态的混合。
缺点
- 因为要表达的状态要列出来,所以当画面相对复杂之后,代码的复杂度急剧增加,无法进行局部更新。
- 随着每个状态的变化,恢复前一个状态的数据相对较困难,除非单独针对性的保留旧状态。
- 共同状态更难表达,更难以分享。
- 使用数据绑定非常困难。
使用场景
- 以明确的意图表达 UI 时(意图可以直接更改为状态)
- 加载或错误时可以视为完整状态
- 不需要部分数据修改或先前状态时