文章目录
一、前言
LiveData
是Android
中用来进行数据监听的类。由于一些限制,现在官方推荐使用Flow
进行数据监听。在ktx拓展包中,使用LiveData.asFlow()
可以很方便的将LiveData
转换为Flow
。Flow.asLiveData()
也可以很方便的将Flow
转换为LiveData
二、特点
LiveData通常在ViewModel里面创建,这是因为以下原因。
- 确保系统不会从 Activity 或 Fragment 的
[onResume()](https://developer.android.com/reference/android/app/Activity?hl=zh-cn#onResume())
方法进行冗余调用。 - 确保 Activity 或 Fragment 变为活跃状态后具有可以立即显示的数据。一旦应用组件处于
STARTED
状态,就会从它正在观察的LiveData
对象接收最新值。只有在设置了要观察的LiveData
对象时,才会发生这种情况。
三、添加依赖
implementation 'androidx.lifecycle:lifecycle-livedata:2.4.0'
// or
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
四、初步使用示例
创建
class NameViewModel : ViewModel() {
// Create a LiveData with a String
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// Rest of the ViewModel...
}
观察
class NameActivity : AppCompatActivity() {
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
private val model: NameViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Other code to setup the activity...
// Create the observer which updates the UI.
val nameObserver = Observer<String> { newName ->
// Update the UI, in this case, a TextView.
nameTextView.text = newName
}
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.currentName.observe(this, nameObserver)
}
}
赋值
model.currentName.value = anotherName //该方式不可以在子线程使用
//or
model.currentName.postValue(anotherName) //该方式可以在子线程使用
在LiveData
中只能进行数据监听而不能进行更改,更改的话只能使用MutableLiveData
。为了遵从设计原则,可以使用以下范例:
private val _liveData: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
val liveData: LiveData<String> = _liveData
需要注意的是,倘若LiveData创建的时候如果有值会在添加监听后立刻触发监听
五、Transformations
在Lifecycle
软件包会提供 Transformations
类。该类会对LiveData进行一个辅助操作。其中主要会用到map(LiveData)
和switchMap(LiveData)
。示例如下(Transformations
源码也有示例):
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = Transformations.map(userLiveData) {
user -> "${user.name} ${user.lastName}"
}
private fun getUser(id: String): LiveData<User> {
...
}
val userId: LiveData<String> = ...
val user = Transformations.switchMap(userId) { id -> getUser(id) }
主要用途是当其中一个LiveData
进行改变时候会触发其于依赖于该LiveData
的LiveData
。这两个函数的唯一区别就是map(LiveData)
返回普通类型,switchMap(LiveData)
返回LiveData
类型。
六、MediatorLiveData
该类可以进行数据源的合并,以下为MediatorLiveData
源码中的示例:
LiveData liveData1 = ...;
LiveData liveData2 = ...;
MediatorLiveData liveDataMerger = new MediatorLiveData<>();
liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
对MediatorLiveData
实现监听的话,其依赖的数据源任何一个改变都会触发该对象的监听。
七、liveData{}
下面演示一种写法(源自androidx.lifecycle.LiveDataScope
源码,源码中有更多示例):
val data : LiveData<Int> = liveData {
delay(3000)
emit(3)
}
该写法需要依赖于ktx拓展,主要是使用协程进行编写的。这种写法表示如果在非活动状态(也就是生命周期Start和Resume之外的时候)会在3秒后取消。当变成活动时候会重新计算。
如果不需要延时可以写成下面方式:
val data : LiveData<Int> = liveData {
val queryUserCount = query()
emit(queryUserCount)
}
八、Livedata建立observe时,抛Cannot add the same observer with different lifecycles的问题
推测是因为ViewModel里面持有静态变量导致无法销毁,后面再次进入时候又一次添加了observe导致的该问题。但是没有测试。模拟的方式是,在onstart里面进行初始化,不过该方式也未实践