LiveData的优点(摘自https://blog.youkuaiyun.com/m0_37778101/article/details/103789862)
-
UI和实时数据保持一致,因为LiveData采用的是观察者模式,这样一来就可以在数据发生改变时获得通知,更新UI。
-
避免内存泄漏,观察者被绑定到组件的生命周期上,当被绑定的组件销毁(destroy)时,观察者会立刻自动清理自身的数据。
-
不会再产生由于Activity处于stop状态而引起的崩溃,例如:当Activity处于后台状态时,是不会收到LiveData的任何事件的。
-
RxLifeCycle: 可以在一定的时机如onstop,ondestroy取消订阅,但是在onstart,OnResume不会恢复,而liveData可以做到
-
不需要再解决生命周期带来的问题,LiveData可以感知被绑定的组件的生命周期,只有在活跃状态才会通知数据变化。
-
实时数据刷新,当组件处于活跃状态或者从不活跃状态到活跃状态时总是能收到最新的数据。
-
解决Configuration Change问题,在屏幕发生旋转或者被回收再次启动,立刻就能收到最新的数据。
关于LiveData的文章,网络上还有很多,对LiveData剖析的极为详尽。科普不是本文要做的事情,自认为也不会比前辈做的更好。本文,仅是自己实践过程中,对认为具有困惑的几点,
做个小小的总结。
1、LiveData的postValue和setValue接口的区别和联系。
查看LiveData的postValue调用如下:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
发现postValue接口最终会切换主线程,调用setValue接口。因此我认为postValue和setValue本质上要做的事情是差不多的,区别在于setValue只能在主线程中调用。而postValue可以在子线程中调用。
2、LiveData有粘性事件吗?(粘性事件是可以被事件发出之后才注册的订阅者接收到,也可以在事件发出之后通过主动查询获取事件内容)
有
3、如何消除LiveData的粘性事件?(一种思路)
注册观察者事件时,通过hook技术,改变系统的一些参数。
/**
* hook方法 hook系统源码 改变系统的一些参数
* @param observer
*/
// private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
// new SafeIterableMap<>();
private void hook(Observer<T> observer) throws Exception {
//获取到LiveData的类对象
Class<LiveData> liveDataClass = LiveData.class;
// 获取到mObservers的反射对象
Field mObserversField = liveDataClass.getDeclaredField("mObservers");
// 让mObserversField可以被访问
mObserversField.setAccessible(true);
// 获取到这个mObserversField的值
Object mObservers = mObserversField.get(this);
// 获取到mObservers的get方法的反射对象
Method get = mObservers.getClass().getDeclaredMethod("get", Object.class);
// 设置这个反射对象可以被访问
get.setAccessible(true);
// 执行这个方法 得到Entry
Object invokeEntry = get.invoke(mObservers, observer);
// 定义一个空的对象 LifecycleBoundObserver
Object observerWrapper = null;
if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
Object key = ((Map.Entry)invokeEntry).getKey();
observerWrapper = ((Map.Entry)invokeEntry).getValue();
}
if(observerWrapper == null){
throw new NullPointerException("ObserverWrapper不能为空");
}
// 获取到ObserverWrapper的类对象
Class<?> superclass = observerWrapper.getClass().getSuperclass();
// 获取搭配这个类中的mLastVersion成员变量
Field mLastVersionField = superclass.getDeclaredField("mLastVersion");
mLastVersionField.setAccessible(true);
// 获取到mVersion的反射对象
Field mVersionField = liveDataClass.getDeclaredField("mVersion");
// 打开权限
mVersionField.setAccessible(true);
// 得到的就是mVersion在当前类中的值
Object o = mVersionField.get(this);
// 把它的值给mLastVersion
mLastVersionField.set(observerWrapper,o);
}
4、注册的观察者,什么时候会被遍历?
(1) postValue、setValue被调用的时候。
(2) 生命周期发生改变的时候。
5、当注册的观察者被遍历时,满足哪些条件,会调用回调接口onChange?
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
(1) observer.mActive的值为true
(2) observer.shouldBeActive()的值为true
(3) observer.mLastVersion >= mVersion
更多查看源码,这里就不一一展开了。
6、Android架构组件liveData的最低要求
见https://blog.youkuaiyun.com/n_fly/article/details/112462662