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

4 参考代码

最后修改:2020 年 06 月 04 日
如果觉得我的文章对你有用,请随意赞赏