为了活动小家电-UI状态管理(三)

42 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

为了活动小家电,接着上篇搞!

方案三

创建和管理一个状态数据类

ViewModel

@HiltViewModel
class ProgramThreeViewModel @Inject constructor(
    private val repository: LibraryRepository
) : ViewModel() {

    data class State(
        val loading: Boolean = true,
        val error: Boolean = false,
        val name: String = "",
        val price: String = ""
    )

    private val _state: MutableStateFlow<State> = MutableStateFlow(State())
    val state: StateFlow<State> = _state.asStateFlow()

    init {
        viewModelScope.launch {
           val response = repository.getBookInfo()
            _state.update { state -> state.copy(loading = true) }

            response
                .onSuccess { bookInfo ->
                    _state.update { state ->
                        state.copy(
                            loading = false,
                            name = bookInfo.name,
                            price = bookInfo.price
                        )
                    }
                }
                .onFailure {
                    _state.update { state ->
                        state.copy(
                            loading = false,
                            error = true
                        )
                    }
                }
        }
    }
}

Activity

@AndroidEntryPoint
class ProgramThreeActivity : BindActivity() {

    private val viewModel: ProgramThreeViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleScope.launch {
            viewModel.state.collect { state ->
                // 加载中展示
                binding.ivLoading.isVisible = state.loading
                // 加载异常展示
                binding.ivError.isVisible = state.error
                // 书名展示
                binding.tvName.text = state.name
                // 价格展示
                binding.tvPrice.text = state.price
            }
        }
    }
}

优点

  • 所有必要的状态都可以包含在一个数据中,只需要调整数据值即可,因此可以方便地处理 UI 的业务逻辑。
  • 通过使用数据类,提供了一种强大的局部更新方法,数据类的copy方法。
  • 改变 UI 的代码没有分散相对比较集中,都是统一返回的,所以代码分析很方便。
  • 结合LiveData或StateFlow的功能和distinctUntilChanged(根据条件,如果生产的值和上个发送的值相同,值就会被过滤掉),可以应用到想要的形式的数据绑定

缺点

  • 虽然copy保证了一定程度的安全性,但它很容易受到数据更改的并发问题的影响。
  • 当屏幕变得更复杂时,数据类所需的属性急剧增加。
  • 数据类 即使特征值发生变化,也需要注意动画

使用场景

  • 如果对 UI 的小修改频繁发生
  • 如果你的 UI 业务逻辑比较复杂
  • 当频繁使用状态组合时
  • 如果加载或错误也可以包含在状态中并进行处理

为了活动小家电,下篇继续搞