美文网首页android
LiveData的使用介绍

LiveData的使用介绍

作者: dashingqi | 来源:发表于2020-06-21 00:51 被阅读0次
    Android_Banner.jpg

    简介

    • LiveData是JetPack提供的一种响应式编程组件,它可以包含任何数据类型的数据(String,Int,Boolean等)。
    • LiveData在数据发生变化的时候,会通知给观察者。
    • 一般情况下,LiveData与ViewModel配合使用的,在这个前提下,LiveData都是在ViewModel中声明的。但是也是可以单独进行声明使用的。
      • LiveData是具有生命感知的,它的数据源一般都是ViewModel提供的,这样当数据源发生变化我们通过LiveData可以通知给观察者。(通常我们的观察者是组册在Activity或者Fragment中的)
      • 当然也不能忽略生命周期感知这个提点,可以这样理解,当观察者处于Active状态的时候,LiveData发生变化观察者可以收到,但是观察者处于Paused或者Destoryed状态,那么观察者就不能收到LiveData的通知了
    • 在MVVM中,我们可以使用LiveData帮助ViewModel向Activity或者Fragment进行通信
      • 因为ViewModel的生命周期都要比Activity要长的,所以我们不能让ViewModel持有Activity的引用,如果这时我们能在Activity中观察ViewModel中的LiveData,那么就不回因为ViewModel持有activity而造成的内存泄漏问题。
    • LiveData是一个抽象类,其中我们常用的是它的实现子类 MutableLiveData,它是一个可变的LievData,主要有如下几个操作api
      • getValue():用于从LiveData中获取到包装的数据
      • setValue():用于给LiveData设置数据
      • postValue():同样也是给LiveData设置数据
    • postValue与setValuede 区别
      • setValue():只能作用于UI线程中,如果在工作线程中使用,会发生crash
      • postValue:可以用于工作线程中(非UI线程 ),当然在UI线程中也是可用的。

    使用

    基本使用

    我们知道在MVVM中ViewModel是作为数据的持有者,而Activity或者Fragment是作为UI的载体(PhoneWindwo),在MVVM中我们一般是使用DataBinding,将XML文件自动编译成一个XXXDataBinding的文件,通过在Activity中,用这个XXDataBinding去绑定我们的数据持有者ViewModel,然后在xml引入这个ViewModel,并且去动态绑定我们ViewModel中的LiveData或者Observable。达到一个数据监听的作用。

    • 场景设定:我们有一个ViewModel,内部有一个LiveData包装着String类型,同时在Activity中获取到这个ViewModel,注册一个观察者去监听ViewModel中的LiveData,当我们点击按钮设置一个数据源给LiveData,然后在观察者中去更新xml文件中的一个text。

    • 代码实现如下

      class LiveDataMainActivity : AppCompatActivity() {
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_live_data_main)
              //获取到ViewModel(此种方式获取ViewModel要在Lifecycle2.2.0之后哟!)
              var viewModelDemo2 = ViewModelProvider(this)[ViewModelDemo2::class.java]
              //注册一个观察者,用于观察LiveData,当LiveData的数据源发生改变会通知到观察者中
              viewModelDemo2.liveData.observe(this, Observer {
                  it?.let { value ->
                      tvText.text = value
                  }
      
              })
      
              btnChange.setOnClickListener {
                  viewModelDemo2.liveData.postValue("i am coming ")
      
              }
      
      
          }
      }
      
      class ViewModelDemo2 : ViewModel() {
      
          var liveData = MutableLiveData<String>()
      }
      
    map

    这里说的map实则是调用了Transformations#map()方法,通过该方法可以将我们的LiveData进行数据类型转换成新类型的LiveData,然后在Activity中注册新LiveData的观察者就能拿到数据源了,

    说的可能比较抽象,以列子来说明吧

    • 场景设定:有一个Person,包含姓名和性别,但是我们的UI控件上只用来显示姓名的,这时我们可以通过map这种方式来做处理

    • 代码实现如下

      class MapLiveDataMainActivity : AppCompatActivity() {
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_map_live_data_main)
              var viewModel = ViewModelProvider(this)[MapLiveDataViewModel::class.java]
              var person = Person()
              person.name = "DashingQi"
              person.sex = "man"
      
              viewModel.transformLiveData.observe(this, Observer {
                  it?.let { value ->
                      tvText.text = value
                  }
      
              })
              setUser.setOnClickListener {
                  viewModel.userLiveData.postValue(person)
              }
      
      
          }
      }
      
      class MapLiveDataViewModel : ViewModel() {
      
          var userLiveData = MutableLiveData<Person>()
      
          /**
           * 使用Transformations#map转换成一个新的LiveData
           * 第一个参数是我们要进行转化的LiveData。里面包装了我们需要的数据
           * 第二个参数是我们要进行转化的函数
           * 这样当userLiveData的数据源发生变化的时候,我们transformLiveData的观察者就能收到转化后的数据源了
           */
          var transformLiveData = Transformations.map(userLiveData) {
              it.name
          }
      }
      
    switchMap

    switchMap同样是Transformations中的,该方法同样有两个参数 参数一:LiveData 参数二:函数转换体

    与map不同,switchMap的函数转化中必须要返回一个LiveData对象,

    参数一:我们可以作为一个条件决定函数转化中返回什么类型的LiveData,也可以将其包装的数据作为新的LiveData在转化函数中返回

    • 场景设定:同样有一个Person,是一个外国人,有firstName和lastName,不过我们有一个条件就是,UI控件只能显示lastName或者firstName

    • 代码实现如下

      class SwitMapMainActivity : AppCompatActivity() {
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_swit_map_main)
              var switchMapViewModel = ViewModelProvider(this)[SwitchMapViewModel::class.java]
              switchMapViewModel.transformationsLiveData.observe(this, Observer {
                  it.let { value ->
                      nameText.text = value
                  }
      
              })
      
              setUser.setOnClickListener {
                  var person = Person()
                  person.firstName = "zhang"
                  person.lastName = "qi"
                  //当切换 true或者false观察控件显示是否发生变化了呢
                  person.condition = false
                  switchMapViewModel.conditionLiveData.postValue(person)
              }
          }
      }
      class SwitchMapViewModel:ViewModel() {
      
          var conditionLiveData = MutableLiveData<Person>()
      
          val transformationsLiveData = Transformations.switchMap(conditionLiveData){
               if (it.condition){
                  MutableLiveData(it.firstName)
              }else{
                 MutableLiveData(it.lastName)
             }
          }
      }
      class Person {
          var name = ""
          var sex = ""
          var firstName = ""
          var lastName = ""
          var condition = false
      }
      
    合并多个LiveData的数据源

    该操作使用的是MediatorLiveData,它继承MutableLiveData,在原有功能的基础上,新增了合并多个LiveData的数据源的功能,实则就是一个组件监听多个LiveData,通过addSource方法

    • 场景设定:我们有一个控件,和两个LiveData(L1,L2),当L1的数据源发生变化,我们控件显示L1的,当L2数据源发生变化实现L2的,可能我们的做法就是在ViewModel中声明两个LiveData,然后在Activity中分别注册这两个LiveData的观察者,当数据源发生改变去更新UI,其实我们可以使用MediatorLiveData去简化这个操作,不用在Activity中注册两个LiveData的观察者

    • 代码实现

      class MediatorLiveDataMainActivity : AppCompatActivity() {
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_mediator_live_data_main)
              var mediatorLiveDataViewModel =
                  ViewModelProvider(this)[MediatorLiveDataViewModel::class.java]
              mediatorLiveDataViewModel.mediatorLiveData.observe(this, Observer {
                  text.text = it
              })
      
              setLiveData1.setOnClickListener {
                  mediatorLiveDataViewModel.liveData1.postValue("liveData1")
              }
      
              setLiveData2.setOnClickListener {
                  mediatorLiveDataViewModel.liveData2.postValue("liveData2")
              }
          }
      }
      class MediatorLiveDataViewModel : ViewModel() {
          var liveData1 = MutableLiveData<String>()
          var liveData2 = MutableLiveData<String>()
      
          var mediatorLiveData = MediatorLiveData<String>()
      
      
          init {
              mediatorLiveData.addSource(liveData1) {
                  Log.d("perform livedata1", it)
                  mediatorLiveData.postValue(it)
              }
      
              mediatorLiveData.addSource(liveData2) {
                  Log.d("perform livedata2", it)
                  mediatorLiveData.postValue(it)
              }
          }
      }
      

    总结

    • 主要介绍了一下LiveData的几种使用场景
    • LiveData作为ViewModel和Activity之间的桥梁,具有生命感知,并且不会存在内存泄漏,其实靠的是Lifecycle组件
    • LiveData在内部使用了Lifecycle组件,来感知生命周期的变化,当Activity销毁的时候也会释放掉引用,防止内存泄漏。
    • LiveData的数据源发生变化只会通知到处于Active状态的Activity中的观察者,当Activty由不可见变为可见的状态,那么此时观察者会收到通知,实则为了减少性能损耗嘛
      • 当Activity处于不可见状态时,LiveData发生了多次改变,当变成可见状态时只能收到最新的变化通知

    相关文章

      网友评论

        本文标题:LiveData的使用介绍

        本文链接:https://www.haomeiwen.com/subject/lugnxktx.html