前言
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData
具有生命周期感知能力,意指它遵循其他应用组件(如 activity
、fragment
或 service
)的生命周期。这种感知能力可确保 LiveData
仅更新处于活跃生命周期状态的应用组件观察者。
说简单就是 LiveData
是一个可观察的数据存储类,内部借助了 Lifecycle
,从而实现了生命周期感知,同时,这个可观察指的是,在其存储的数据更新时,它会去通知观察者。又因为生命周期感知的存在,所以可以做到 何时通知、何时解绑,从而做到安全无泄漏,就是如此:)
作者:Petterp
链接:https://juejin.cn/post/7173494700081414181
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
特点
LiveData通常在ViewModel里面创建,这是因为以下原因:
1.确保系统不会从 Activity 或 Fragment 的 [onResume()]
方法进行冗余调用。
2.确保 Activity 或 Fragment 变为活跃状态后具有可以立即显示的数据。一旦应用组件处于 STARTED 状态,就会从它正在观察的 LiveData
对象接收最新值。只有在设置了要观察的 LiveData
对象时,才会发生这种情况。
添加依赖
implementation 'androidx.lifecycle:lifecycle-livedata:2.4.0'
// or
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
初步使用示例
在ViewModel里创建LiveData
class NameViewModel : ViewModel() {
// Create a LiveData with a String
val mLiveData: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// Rest of the ViewModel...
}
在activity/fragment里观察
class NameActivity : AppCompatActivity() {
private val mViewModel: NameViewModel by viewModels()
private lateinit var otcModelManager: OTCModelManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
otcModelManager = SingleInstanceProvider.get(OTCModelManager::class.java)
val nameObserver=Observer<String>{newName->
nameTextView.text = newName
}
mViewModel.mLiveData.observe(this,nameObserver)
otcModelManager.getFaceDetectionQRCodeData(mViewModel.mLiveData)
}
}
class OTCModelManager() {
fun getFaceDetectionQRCodeData(mLiveData: MutableLiveData<String>){
mLiveData.value = anotherName //该方式不可以在子线程使用
//or
mLiveData.postValue(anotherName) //该方式可以在子线程使用
}
}
Transformations
在Lifecycle 软件包会提供 Transformations 类。该类会对LiveData进行一个辅助操作。其中主要会用到map(LiveData)
和switchMap(LiveData)
map(LiveData)的参数mapFunction(在kotlin里使用lambda表达式实现)的
返回普通类型
public static <X, Y> LiveData<Y> map(
LiveData<X> source,
final Function<X, Y> mapFunction) {...}
使用案例:
val getFaceDetectionQRCodeSucLiveData:MutableLiveData<FaceDetectionQRCodeBean>
by lazy {MutableLiveData<FaceDetectionQRCodeBean>() }
val stringLiveData : LiveData<String> = Transformations.map(getFaceDetectionQRCodeSucLiveData) { bean ->
"${bean.merchantName}"
}
stringLiveData.observe(owner=reference?.get()!!, onChanged = {
LogUtil.e(TAG, "输出 stringLiveData 数据=${it}") //输出 stringLiveData 数据=ai全球鹰
})
switchMap(LiveData)的参数switchMapFunction(在kotlin里使用lambda表达式实现)
返回LiveData
类型。
public static <X, Y> LiveData<Y> switchMap(
LiveData<X> source,
final Function<X, LiveData<Y>> switchMapFunction) {...}
使用案例
val getFaceDetectionQRCodeSucLiveData:MutableLiveData<FaceDetectionQRCodeBean>
by lazy { MutableLiveData<FaceDetectionQRCodeBean>() }
val getJGPushReceiverLiveData: MutableLiveData<String?>
by lazy{ MutableLiveData<String?>() }
val resultLiveData: LiveData<String?> = Transformations.switchMap(getFaceDetectionQRCodeSucLiveData) {bean->
getJGPushReceiverLiveData.value=bean.merchantLogo
getJGPushReceiverLiveData//lambda的最后一行要返回一个 LiveData对象
}
resultLiveData.observe(owner=reference?.get()!!, onChanged = {
LogUtil.e(TAG, "输出 resultLiveData 数据=${it}") //输出 resultLiveData 数据=https://test-consumer.aiyzy.com//file/image/1580808861459533825
})
抛Cannot add the same observer with different lifecycles的问题
如果一个activity,在onCreate的时候建立Livedata监听,当此activity启动两遍的时候,会抛出Cannot add the same observer with different lifecycles异常,原因是使用了lamda表达式。
使用lamda表达式建立监听,当Activity未finish的时候,再一次启动的时候,就会报异常,
原因是在同一个类里 使用lamda表达式 实例化的对象,引用外部的静态方法
或者静态引用
,导致是同一个实例。
public class MyActivity extends AppCompatActivity {
static String TEST_NAME = "HAHHA";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final int num = 1;
liveData.observe(this, value-> {
// 内部新建实例
Gson gson = new Gson;
// 只是使用了外部的基本类型
int thisNum = num;
// 调用外部的静态方法和静态引用
show(TEST_NAME );
});
}
static void show(String name){
.....
}
}
如何避免这个异常呢?
引用了外部的非静态引用
或者非静态的方法
,两个相同的activity下,就不是同一个实例,就不会报这个异常错误了。
String EXTAR_NAME = "HAHHA";
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final int num = 1;
liveData.observe(this, value-> {
Gson gson = new Gson;
// 调用外部静态引用
String str = EXTAR_NAME;
// 调用外部非静态方法
show(EXTAR_NAME);
});
}
}
void show(String name){
.....
}