首先抛出个异常
FATAL EXCEPTION: main
Process: com.lion.media, PID: 5513
java.lang.IllegalArgumentException: Cannot add the same observer with different lifecycles
at androidx.lifecycle.LiveData.observe(LiveData.java:199)
这是在livedata.observe(this) {
// ...
}触发的异常
下面分析下
从源码看,试图将observer在两个lifecycle注册到livedata就会触发这个异常,正常情况下很难遇到这个问题,但是有些情况容易出现问题:
前提:livedata的生命周期比和订阅这个livedata页面长
页面没有正常销毁,又创建一次
两个页面用同一个类,比如Fragment, 这个fragment里订阅livedata
反编译发现:
如果lambda内没有引用外部非静态成员,会被编译程类似单例的类
livedata.observe((LifecycleOwner)this, -$$Lambda$RadioCatalogFragment$caW7Hi16aKYOCUVWVHqIazPGd8s.INSTANCE);
一般情况是new出来的
livedata.observe((LifecycleOwner)this, new -$$Lambda$RadioCatalogFragment$aQGE2mZtdMX-nI-7aVkDUov6kPw(this))
如何解决:
不要使用lambda,改用object
lambda内引用外部非静态变量或方法
另外网传一种方案:
class SafeMutableLiveData<T>: MutableLiveData<T>() {
private var weakLifecycleOwner: WeakReference<LifecycleOwner>? = null
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
weakLifecycleOwner?.get()?.let {
removeObservers(it)
}
weakLifecycleOwner = WeakReference(owner)
super.observe(owner, observer)
}
override fun setValue(value: T) {
try {
super.setValue(value)
} catch (e: Exception) {
super.postValue(value)
}
}
}
这种方案不可取,原因是如果这个livedata有很多个页面都要订阅时,就错误了,setValue方法到不错,可用