@universal
2023-02-08T02:22:14.000000Z
字数 1452
阅读 113
未分类
observer的时候会传入LifecycleOwner,liveData的observer方法中会将owner和observer包装成wrapper(LifecycleEventObserver),最后owner.getlifecycle().addObserver()实现感知生命周期的变化的能力。
虽然observer是匿名内部类,但是liveData具有感知生命周期的能力,会在DESTORY状态时自动移除观察者,从而避免内存泄漏。
是。
LiveData中有一个mData存储值,一个mVersion记录版本,每一次的setValue()都会更新这两个值,通知观察者时,observer里会有一个mLastVersion记录上一次被通知时版本,如果mLastVersion >= mVersion,那么观察者不会调用 onChanged() 方法。但是如果是新创建的观察者,它的mLastVersion是初始值,这时候新观察者在添加时就会触发一次老值的分发(也就是LiveData的粘性,新观察者被老值通知到了)。
另外:
LiveData通知的场景:
1. 值变化,通知所有观察者
2. 新增观察者,或者已添加的某个观察者生命周期发生变化(如变化为START),会通知单个观察者
LiveData分发的条件:
1. 观察者是否活跃(mActive)
2. 观察者的生命周期是否活跃
3. 观察者的版本号是否最新
会造成一些页面的切换时,切换回上一层页面,上层页面又执行一次旧数据的逻辑。
解决方案:
1. Value中添加一个是否被消费过的bool值,如果没被消费过,再处理具体业务逻辑
2. 反射修改 mLastVersion为最新版本号,但是这样的做法会破坏粘性,只适用于特定场景
3. 官方的解决方案:SingleLiveEvent(继承自MutableLiveData), SingleLiveEvent中定义一个值表示是否被消费过,在observe()方法中包一层observe{},在它onChange时判断一下这个值,如果没有被消费过,再调用真正的观察者的onChange通知数据更新
4. Kotlin Flow也可以解决(不会,面试的时候能不说就不说吧。。)
postValue()会丢失数据
postValue会先把值暂存mPendingData变量,等到runnable真正执行的时候才会将mPendingData赋值给mData,如果在runnable执行之前再调用postValue,mPendingData被覆盖,就会造成数据丢失。
解决:如果在主线程就直接使用setValue,如果不在,手动延一下postVaule的频率。
绑定viewLifecycleOwner而不是fragment本身,如果是fragment之间的切换,不会调用到DESTORY阶段,就会导致观察者被通知执行响应逻辑,但是view会因为fragment的onDestroyView变为DESTORY阶段。
CoroutineLiveData,将更新 LiveData值的操作封装到一个挂起方法中, 可以通过协程上下文指定执行的线程。