Android中用ViewModel优雅地管理数据
前言
将应用的界面数据与界面(Activity/Fragment)分离可以让您更好地遵循我们前面讨论的单一责任原则。activity 和 fragment 负责将视图和数据绘制到屏幕上,而 ViewModel 则负责存储并处理界面所需的所有数据。
数据变量从 XXFragment 移至 XXViewModel 类
- 将数据变量
score、currentWordCount、currentScrambledWord移至XXViewModel类。
class XXViewModel : ViewModel() {
private var score = 0
private var currentWordCount = 0
private var currentScrambledWord = "test"
...请注意这些属性仅对
ViewModel可见,界面无法对其进行访问
想要解决此问题,就不能将这些属性的可见性修饰符设为 public,不应该让数据可被其他类修改。因为外部类可能会以不符合视图模型中指定的游戏规则的预料外方式对数据做出更改。外部类有可能会将 score 更改为其他错误的值。
在 ViewModel 之内,数据应可修改,数据应设为 private 和 var。而在 ViewModel 之外,数据应可读取但无法修改,因此数据应作为 public 和 val 公开。为了实现此行为,Kotlin 提供了称为后备属性的功能。
后备属性
使用后备属性,可以从 getter 返回确切对象之外的某些其他内容。
Kotlin 框架会为每个属性生成 getter 和 setter。
对于 getter 和 setter 方法,可以替换其中一个方法或同时替换两个方法,并提供自定义行为。为了实现后备属性,需要替换 getter 方法以返回只读版本的数据。后备属性示例:
private var _count = 0
val count: Int
get() = _count举例而言,在应用中,需要应用数据仅对 ViewModel 可见:
在 ViewModel 类之内:
_count属性设为private且可变。因此,只能在ViewModel类中对其访问和修改。惯例是为private属性添加下划线前缀。
在 ViewModel 类之外:
- Kotlin 中的默认可见性修饰符为
public,因此count是公共属性,可从界面控制器等其他类对其进行访问。由于只有get()方法会被替换,所以此属性不可变且为只读状态。当外部类访问此属性时,它会返回_count的值且其值无法修改。这可以防止外部类擅自对ViewModel内的应用数据进行不安全的更改,但允许外部调用方安全地访问该应用数据的值。
将后备属性添加到 currentScrambledWord
- 在
XXViewModel中,更改currentScrambledWord声明以添加一个后备属性。现在,只能在XXViewModel中对_currentScrambledWord进行访问和修改。界面控制器XXFragment可以使用只读属性currentScrambledWord读取其值。
private var _currentScrambledWord = "test"
val currentScrambledWord: String
get() = _currentScrambledWord- 在
XXFragment中,更新updateNextWordOnScreen()方法以使用只读的viewModel属性currentScrambledWord。
private fun updateNextWordOnScreen() {
binding.textViewUnscrambledWord.text = viewModel.currentScrambledWord
}- 在
XXFragment中,删除onSubmitWord()和onSkipWord()方法内的代码。稍后您将实现这些方法。现在,您应该能够不出错误地编译代码了。
注意:勿公开 ViewModel 中的可变数据字段,确保无法从其他类修改此数据。ViewModel 内的可变数据应始终设为 private
作者:子不语Any
链接:https://juejin.cn/post/7224496484254810167
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
链接:https://juejin.cn/post/7224496484254810167
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。