1 简介
LivaData 是Jetpack提供的一种响应式编程组件。它可以包含任何类型的数据。并在数据发生变化的时候通知给观察者(通常是UI控制器)。LiveData特别适合于ViewModel结合一起使用。即ViewModel储存用户界面数据。并将其标记为LiveData。这样数据发生改变都会自动通知给UI控制器以刷新显示。
2 通过UI控制器为中介的使用步骤
视图在XML布局中定义,并且这些视图的数据保存在ViewModel对象中。每个视图及其对应的之间ViewModel是一个UI控制器,它充当它们之间的中继。
2.1. 添加依赖
它的依赖和ViewModel的依赖一样,而且它们通常也是组合使用。
在build.gradle(module:app)的dependencies块内,添加
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
2.2. 将ViewModel中的成员数据类型修改为MutableLiveData
将原本的数据类型修改为MutableLiveData的对应泛型。
class GameViewModel : ViewModel(){
// var word = ""
var word = MutableLiveData<String>()
// var score = 0
var score = MutableLiveData<Int>()
init{
word.value = ""
score.value = 0
}
}
2.4. 封装为LiveData
将之前的MutableLiveData设置为私有。使其对外不可见,这样外部就不可修改了。同时暴露可见但不可修改的的LiveData给外部使用。
class GameViewModel : ViewModel(){
private var _word = MutableLiveData<String>()
private var _score = MutableLiveData<Int>()
// 封装LiveData
val word : LiveData<String>
get() = _word
val score: LiveData<Int>
get() = _score
init{
_word.value = ""
_score.value = 0
}
}
2.5. 在UI控制器中设置观察者
将自身设置为某个LiveData的观察者,在该数据发生变化时,调用回调。
其中的viewLifecycleOwner实际是调用了GameFragment自身的getViewLifecycleOwner()方法。
class GameFragment : Fragment() {
private lateinit var viewModel: GameViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
.......
viewModel = ViewModelProvider(this)[GameViewModel::class.java]
// 添加LiveData观察者,观察者为自身。
viewModel.score.observe(viewLifecycleOwner, Observer {
binding.scoreText.text = it.toString()
})
......
}
}
3 直接将LiveData绑定到view的使用
如果布局中的视图直接与ViewModel对象中的数据进行通信,而不依赖于UI控制器作为中介,则会更加简单。
3.1. 在片段对应的XML布局文件中,添加绑定变量
绑定变量名字可以自行定义,类型须为自己拓展的ViewModel。
<layout ...>
<data>
<variable
name="gameViewModel"
type="com.example.android.guesstheword.screens.game.GameViewModel" />
</data>
<androidx.constraintlayout...
3.2 在Activity/Fragment文件中将viewModel传递到数据绑定中
// gameViewModel为在xml布局中定义的变量名
// viewModel为在fragment/activity中关联的数据模型变量
binding.gameViewModel = viewModel
3.3 使用侦听器绑定事件处理
在视图(xml)上直接设置侦听器。并添加事件处理。
这使得视图按钮的监听操作不必写在UI控制器里
<Button
android:id="@+id/skip_button"
...
android:onClick="@{() -> gameViewModel.onSkip()}"
... />
<Button
android:id="@+id/correct_button"
...
android:onClick="@{() -> gameViewModel.onCorrect()}"
... />
3.4 将LiveData添加到数据绑定
LiveData对象可用作数据绑定源,以自动将有关数据更改的信息通知给UI(xml)
android:text = "@{gameViewModel.word}"
要使其自动更新生效,还需将当前活动(UI控制器)设置为binding变量的生命周期所有者
binding.lifecycleOwner = this
// 或者写为
binding.lifecycleOwner = viewLifecycleOwner