Livedata:感知生命周期变化,如何更新数据?避免内存泄漏,黏性事件
目录
Livedata定义
Livedata的Obsever方法
Livedata更新数据的两种方式
setValue
1,同步数据
2,分发数据
3,通知观察者
livedata如何避免内存泄漏
livedata中的黏性事件
Livedata定义
Livedata的定义:具有生命感知的可观察数据持有者,可以感知持有者的生命周期状态,只在持有者活跃时才更新数据
Livedata的使用非常简单,创建一个Livedata对象,然后调用Observer方法,传入要观察的生命周期对象和自定义的观察者
val data1 : LiveData<String> = MutableLiveData("hello world")fun test(){data1.observe(this, object : Observer<String>{override fun onChanged(value: String) {}})}
先来看一下他的Observer方法:
Livedata的Obsever方法
@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {//检测非主线程报错assertMainThread("observe");//检测owner生命周期if (owner.getLifecycle().getCurrentState() == DESTROYED) {// ignorereturn;}//将生命周期owner和自定义观察者observer包装起来,从而可以监听其生命周期变化LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);//包装好的对象,以我们自定义的的观察者为key,存入一个集合ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);//报错检测机制if (existing != null && !existing.isAttachedTo(owner)) {throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {return;}//包装后的对象给到LifecycleRegistryowner.getLifecycle().addObserver(wrapper);}
Livedata中有两个关键元素:当前Livedata的版本号mVersion,和当前的观察者集合mObservers
public abstract class LiveData<T> {//每一个LiveData对象有一个mVersion属性,记住这个属性很关键。
private int mVersion;//一个支持迭代时更新数据的Iterable
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =new SafeIterableMap<>();
}
Livedata更新数据的两种方式
setValue
setValue可以分为三步走:
1,同步数据
@MainThread
protected void setValue(T value) {//主线程检查,非主线程报错assertMainThread("setValue");//版本号+1mVersion++;//更新数据mData = value;//分发数据dispatchingValue(null);
}
2,分发数据
void dispatchingValue(@Nullable ObserverWrapper initiator) {、、省略其他代码
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {//遍历我们定义的观察者的集合considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}
}、、省略其他代码
}
3,通知观察者
considerNotify中对observer的状态进行过滤,以及版本进行判断,全部通过后,使用mObserverde的onChanged进行数据回调。
private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}//生命周期owner至少是STARTEDif (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;//这里是我们实现的数据改变后回调方法observer.mObserver.onChanged((T) mData);
}@Override
boolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
livedata如何避免内存泄漏
LiveData 通过与其观察者的 (如 Activity/Fragment)生命周期绑定来实现免内存泄漏。
- 当通过 observe(LifecycleOwner, Observer) 方法注册观察者时,LiveData 会将 Observer 和 LifecycleOwner 包装成一个 LifecycleBoundObserver 对象
- 这个包装对象实现了LifecycleEventObserver接口,从而能够监听生命周期变化
- 当关联的lifecycle对象生命周期变为Destory时,Livedata会自动地将这个观察者从列表中移除,这样就确保了观察者不会因为被 LiveData 持有而阻止了 LifecycleOwner 的被回收,从而避免了内存泄漏。
livedata中的黏性事件
“黏性事件”是指:当一个新的观察者开始观察 LiveData 时,如果该 LiveData 之前已经设置过值,那么这位新观察者会立即收到最后一次设置的数据(即最新数据)。
当生命周期对象的生命周期变化时,会走一遍事件分发,数据回调流程
这个特性的实现原理主要依赖于一个版本号(mVersion)机制:
- 每次通过 setValue() 或 postValue() 更新数据时,mVersion 都会递增。
- 每个观察者包装类 (ObserverWrapper) 内部都记录着自己最后一次接收到的数据的版本号 (mLastVersion)。
- 当观察者的生命周期变为活跃状态时,LiveData 会检查其 `mLastVersion` 是否小于 LiveData 当前的 mVersion。如果是,就认为这个观察者的数据是“过时的”,便会立即向其分发最新的数据
参考:
LiveData原理面试一问还不懂?
由浅入深,详解 LiveData 的那些事