Android-JetpackAndroid Architecture Components

Android Kotlin Jetpack之LiveData

2019-08-25  本文已影响1人  水天滑稽天照八野滑稽石

前言

这次我们来聊下LiveData,众所周知,Android里面实现MVVM的方式有2中,一种就是DataBinding,这种方式可以节省一部分通知UI更新的代码,但是布局就不能复用了,另外一种就是我们现在说提到的LiveDate

导入

首先我们要依赖Google仓库,在project -> build.gradle里

allprojects {
    repositories {
        google()
        jcenter()
    }
}

然后是Module -> build.gradle

    def lifecycle_version = "2.0.0"
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

概况

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware,(LiveData是一个可观察的数据持有者类。与常规observable不同,LiveData是生命周期感知的。)

我对LiveData的理解就是:这个一个跟EventBus很类似的东西,任意地方发布事件(liveData改变),我订阅这个事件的能接受到事件(接收到LiveData的改变),但LiveData是生命周期感知的:
1.如果当前的LifecycleOwner不处于活动状态(例如onPasue()、onStop())时,LiveData是不会回调observe()的
2.LiveData没有如果被observe(),此时你调用这个LiveData的postValue(...)/value=...,同样不会被回调

使用

class MyViewModel : ViewModel(){
    /**
     *  这里通过懒加载的方式new了一个MutableLiveData对象
     *  LiveDate是一个抽象类,MutableLiveData是它的实现类
     *  它们之间的关系类似于List和ArrayList
     *  这里的 name 说白了就是一个个 LiveData类型的String
     *  我们只是借助LiveData的特性,本质上还是String
     *  @sample MutableLiveData<List<String>>()
     *  @sample MutableLiveData<Int>()
     *  @sample MutableLiveData<类名>()
     */
    val name: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var model = ViewModelProviders.of(this)[MyViewModel::class.java]
        // 这个this是LifecycleOwner
        model.name.observe(this, Observer {
            text.text = it
        })
        // 更新被观察者数据,LiveData会通知观察者
        model.name.value = "xiao"
    }

    //或者在具体的业务类使用postValue更新数据
    fun modelTest(){
        var model = MutableLiveData<String>()
        model.postValue("xiao")
    }
}

不同的liveData实现类

liveData是一个抽象类,系统实现了2个类,MutableLiveDataMediatorLiveData
MutableLiveData前面已经说过了并展示了怎么用,下面就来说下MediatorLiveData

MediatorLiveData

MutableLiveData的子类,一个更强大的LiveData,它允许我们合并多个 LiveData,任何一个 LiveData 有更新就会发送通知。比如我们的数据来源有两个,一个数据库一个网络,这时我们就有2个 LiveData了,然后我们可以使用 MediatorLiveData 来 merge 这两个 LiveData

class MyViewModel : ViewModel(){
    /**
     *  场景假设:
     *  couldModel是从服务据请求回来的数据
     *  dataModel是数据库请求回来的数据
     *  model是用来UI展示的数据
     *  如果网络请求还没回来就展示先展示数据库的数据
     */
    val couldModel = MutableLiveData<String>()
    val dataModel = MutableLiveData<String>()
    val model = MediatorLiveData<String>()
}

class MainActivity : AppCompatActivity() {

    private lateinit var myModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myModel = ViewModelProviders.of(this)[MyViewModel::class.java]
        initLiveData()
        button1.setOnClickListener {
            //场景模拟,优先返回dataModel数据,随后延迟2S返回coludModel数据
            myModel.dataModel.value = "data"
            Handler().postDelayed({
                myModel.couldModel.value = "cloud"
            },2000)
        }
    }

    //统一处理2个的LiveData
    private fun initLiveData(){
        myModel.apply {
            //通过addSource来merge 多个liveData
            model.addSource(dataModel, Observer {
                model.value = it
            })

            model.addSource(couldModel){
                model.value = it
            }

            //数据变化就更新UI
            model.observe(this@MainActivity, Observer {
                text.text = it
            })
        }
    }
}

map

如果是用过RxJava的小伙伴,对这个操作符肯定不陌生(Kotlin也有哟~),这个操作符的作用是转换,就是我输入一个数据A,我再转成数据B输出

class MyViewModel : ViewModel(){
    val name = MutableLiveData<String>()
    val mapName = Transformations.map(name){
        //在前面增加"map"字符串,也可以做更复杂的工作,如去查数据库并返回
        "map$it"
    }
}

class MainActivity : AppCompatActivity() 
    private lateinit var myModel: MyViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myModel = ViewModelProviders.of(this)[MyViewModel::class.java]
        myModel.mapName.observe(this, Observer {
            text.text = it
        })
        myModel.name.postValue("xiao")
    }
}

switchMap

switchMap的用法和map基本雷同,差异在于返回值不同

   val mapName: LiveData<String> = Transformations.map(name){ }//返回值是LiveData<String>类型
   val switchMap: LiveData<String> = Transformations.switchMap(name){ }//返回值是LiveData<*> 

小结

以上便是LiveData的用法了,说实话内容没我想象中的多...其实LiveData更多还是要配合其他Jetpack组件使用,ORM数据库Room和分页加载Paging,之后我们继续再说

上一篇下一篇

猜你喜欢

热点阅读