Android Kotlin Jetpack之LiveData
前言
这次我们来聊下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个类,MutableLiveData和MediatorLiveData
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,之后我们继续再说