一、 是什么
Google2018年推出的新架构,意图在统一UI组件与架构。
先说一些前置知识。
- androidx
androidx
它是andorid.support
的老弟,android28
以后support
包的替代品,整合了以前杂乱的东西。
在项目里用的时候需要做项目迁移,并且设置
编译版本为
compile SDK=28
android.useAndroidX=true
android.enableJetifier=true
- google sample
谷歌出的相关例子,建议都过一遍。
1.1 业务模式
TODO
1.2 核心组件
涉及框架、生命周期、数据对象等数个组件。
LivaData
,ViewMoedl
、Room
等,基本上都已经封装好在androidx
包内。
关键的源码不多,建议过一遍源码比较好理解。
1.2.1 LiveData
具体路径是androidx.lifecycle.LiveData
。类注释写得很清楚:
LiveData is a data holder class that can be observed within a given lifecycle.
现在我们只把它当作一个holder,可以想象到它将开放的一些方法(外部调用者只需要关心这些)。
set/getData //对持有数据的处理
add/removeObserver //对观察者的处理
业务流程
- 单数据监听
//1.实例化,设置观察者
var liveData = object : MutableLiveData() {}
liveData.observe(this@UserActivity, androidx.lifecycle.Observer {
System.out.println(it)
})
//2.通知数据变化
liveData.value="changed"//主线程
liveData.postValue("post changed")//子线程
- 多数据监听
//1.实例化
var liveFirstData = object : MutableLiveData() {}
liveFirstData.observe(this@UserActivity, androidx.lifecycle.Observer {
System.out.println(it)
})
var liveSecondData = object : MutableLiveData() {}
liveSecondData.observe(this@UserActivity, androidx.lifecycle.Observer {
System.out.println(it)
})
//2.设置观察者
var mediatorLiveData = MediatorLiveData()
mediatorLiveData.addSource(liveFirstData) {
System.out.println(it)
}
mediatorLiveData.addSource(liveSecondData) {
System.out.println(it)
}
//3.通知数据变化
liveFirstData.value="changed"//主线程
liveSecondData.postValue("post changed")//子线程
这个突然出现的MutableLiveData
是什么?它是LiveData
的子类,下边会说。TODO
理解的关键点之一:绑定LiveData的观察者以及它的生命周期
绑定观察者的方法是observe(LifecycleOwner,Observer)
和observeForever(Observer)
区别在于前者会关联
owner
的生命周期,而且在DESTROYED
状态会移除观察者;
而后者不会自动移除观察者,必须手动移除。
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer)
{
assertMainThread("observe");
//绑定时先检测生命周期
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//构建封装类
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
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;
}
//绑定封装类为观察者
owner.getLifecycle().addObserver(wrapper);
}
@MainThread
public void observeForever(@NonNull Observer super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);//触发一次数据分发
}
这里涉及到两个类,LifecycleOwner
和Observer
。后者就是普通的观察者,即用户自定义的业务事件。
前者是LiveCycle
的封装类,androidx
中的Fragment
、Activity
都实现了LifeCycle
。
传入LifecycleOwner
主要是为了与生命周期事件绑定。
拿到LifecycleOwner
后,LiveData
会构建其封装类。同类型的封装类有两个,都是LiveData
的非静态类。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver
private class AlwaysActiveObserver extends ObserverWrapper {
它们的基类ObserverWrapper
主要用来1.管理观察者的数据版本,以及2.封装了由观察者生命周期改变而发起的数据分发的触发机制。
private abstract class ObserverWrapper {
final Observer super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;//在LiveData代码体现
ObserverWrapper(Observer super T> observer) {
mObserver = observer;
}
//影响持有该观察者的LiveData判定【针对该观察者的数据分发行为,是否与其生命周期关联】
//AlwaysActiveObserver返回true
//LifecycleBoundObserver返回大于STARTED
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
/*
*主要用于绑定观察者时自动进行的那一次数据分发
*@param @newActive 新状态是否是活跃
*/
void activeStateChanged(boolean newActive) {
//状态未更新直接返回
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
//注意这里更新了当前livedata的活跃观察者的数量
LiveData.this.mActiveCount += mActive ? 1 : -1;
//如果liveData之前是非活跃态,而当前观察者是活跃态
if (wasInactive && mActive) {
onActive();
}
//如果本次更新后liveData切到非活跃态,且当前观察者也是非活跃的
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
//数据分发
if (mActive) {
dispatchingValue(this);
}
}
}
LiveData
通常会直接调用observer.activeStateChanged(newActive)
触发数据分发。从上面代码看出来,newActive除了影响是否分发,还影响onActive
和onInactive
。
理解的关键点之二:LiveData的数据分发流程
- 数据分发流程
1.第一次:绑定永久观察者时自动触发一次数据分发;绑定生命周期关联的观察者时由系统触发数据分发;
2.第n次:持有者调用set/postValue
触发消息分发;
3.每当mData
被改变,LiveData
内部增加数据的版本号mVersion
;
4.遍历并比较mObservers.mLastVersion
,通知较小版本号的观察者(版本号小说明观察者当前拿到的并不是最新数据)
5.LiveData
自身持有观察者Observer
的引用,在需要时调用observerWrapper.onChanged(T)
通知观察者。
-
外部主动调用触发的数据分发
//数据改变时增加版本号
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);//传null是通知所有观察者
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
//其他线程的分发操作会被阻断
mDispatchInvalidated = true;
return;
}
//确保同一时间只有一个分发操作
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
//通知单独的观察者
considerNotify(initiator);
initiator = null;
} else {
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
//检查有没有异步
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
...
//通知之前检测版本号
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
数据分发的起始点之一是setValue
函数,其中调用了dispatchingValue
。后者内部用到了两个实例级别的标志位mDispatchingValue(正在分发数据)
和mDispatchInvalidated(分发数据无效化、需要重新分发)
。
-
生命周期事件触发的消息分发
//由系统调用的方法 Called when a state transition event happens.
//LiveData.LifecycleBoundObserver 在观察到状态改变时会先检查生命周期
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
-
绑定永久观察者1触发的数据分发
比较简单,上面代码有提到。
- 多线程场景下的数据分发
在多线程的情况下,标志位会阻止后来的线程进入数据分发的流程,同时将mDispatchInvalidated(分发数据无效化、需要重新分发)
置为true
;
同时先到的线程在对initiator
或者全局观察者完成分发后,会重新判定mDispatchInvalidated
无效化标记(见上图32行),触发新一轮的数据分发操作,这样保证了即使在多线程的场景下新数据也不会被漏发。
LiveData
的原理真的大概就这些。
1.2.2 常用的LiveData子类MediatorLiveData
TODO
参考
William_Huang-LiveData的onActive()和onInactive()