前言
在了解LiveData并学习其原理之前,需要先知道Lifecycle的使用以及原理,否则下文某些部分可能较难理解。
传送门-Lifecycle
约定
Observer : 下文无特殊说明都称为观察者
LifecycleOwner: 下文无物特殊说明均称owner(被观察者——具有生命周期)
LiveData是什么
引用源码对于LiveData的注释,个人感觉解释得很到位
/**
* LiveData is a data holder class that can be observed within a given lifecycle.
* This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
* this observer will be notified about modifications of the wrapped data only if the paired
* LifecycleOwner is in active state. LifecycleOwner is considered as active, if its state is
*/
语意大致如下:
LiveData所持有数据可被感知。在LiveData里,观察者与owner成对出现(当然有例外,后面再说)。在LiveData所持有包装过的数据有变化时,观察者处于active状态时回得到通知。
owner状态处于State.STARTED或State.RESUME时观察者被认为是active状态。
简单来说,LiveData作为一种媒介去持有数据,在数据发生改变时,去通知监测owner并处于active状态的观察者作出应对。
案例
public class MyData extends LiveData {
private static final String TAG = "T-MyData";
public MyData(){
setValue("hi");
}
@Override
protected void onActive() {
super.onActive();
Log.d(TAG, "onActive ");
}
@Override
protected void onInactive() {
super.onInactive();
Log.d(TAG, "onInactive ");
}
public void changeValue(String value){
setValue(value);
}
}
public class MainActivity extends AppCompatActivity {
private static final String TAG = "T-MainActivity";
MyData data = new MyData();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
data.changeValue(data.getValue() + "~");
}
});
data.observe(this, new Observer() {
@Override
public void onChanged(@Nullable String value) {
Log.d(TAG, "onChanged: " + value );
}
});
}
}
案例行为:LiveData持有String数据,并在MainActivity(也就是owner)生命周期内,观察者对观察其数据。String初始为“hi”,每点击页面上的按钮String在原有拼接上“~”。在数据改变时,onChanged()可接受到改变的数据。 在点击三次案后让MainActiviy进入不可见状态
日志如下
从日志上看数据已被感知,此外触发了onActive()以及onInactive() , 二者在什么时候会被触发,下文会有说明。
原理
重要函数
对于使用LiveData重要且包含需要注意事项,挑出以预警
- setValue()
protected void setValue(T value) {
assertMainThread("setValue");
.....
}
此函数设置LiveData里的数据,并且执行在主线程里
- postValue()
protected void postValue(T value) {
.....
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
与setValue功能相同,可执行在非主线程
-getValue() : 获取LiveData里的数据,但不保证一定接收到最新数据(比如在异步线程里更新数据被耽误了)
注册过程
前文所述,onwer与观察者称对出现。可通过observe注册。此外,也可通过observeForever进行注册,与observer会有差异。此处针对observe方式先做阐述,observeForver在后文再做比对。
- LiveData.obsever()
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
// owner处于Destroy状态已无注册必要
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
// 将owner与观察者进行绑定
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
// 一个观察者仅仅针对一个onwer
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
// 这里的getLifecycle一般是Lifecycle里说的LifecycleRegistry
owner.getLifecycle().addObserver(wrapper);
}
从代码上看,注册时,先排查owner状态是否合适,紧接着将owner与观察者进行了绑定,且从抛出的异常可以知道,owner与观察者的关系为一对多。此后将包装好的ObserverWrapper交给LifecycleRegistry,这样,就确保了再State.Event事件到达时,ObserverWrapper会接受到讯息。 (Lifecycle知识,忘了去这里->传送门)
绑定过程
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
super(observer);
mOwner = owner;
}
.....
}
private abstract class ObserverWrapper {
final Observer mObserver;
ObserverWrapper(Observer observer) {
mObserver = observer;
}
......
}
这里贴出了LifecycleBoundObserver与其父类ObserverWrapper的部分内容,可见两者分别持有了owner与观察者信息。
到这里,整个注册过程完毕。过程很简单,做个小结
- 绑定owner与观察者,信息收集入LifecycleBoundObserver
- 将LifecycleBoundObserver交接给LifecycleRegistry进行注册,以便Event事件到来时得以接收
感知过程
在Lifecycle知识里知道,Event最终会经过GenericLifecycleObserver的实现类作为中转者经过处理,传达到具体的观察者。从之前的代码截图可以知道LifecycleBoundObserver是GenericLifecycleObserver的实现类,因此能接收到Event事件。
public interface GenericLifecycleObserver extends LifecycleObserver {
void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
}
GenericLifecycleObserver对于Lifecycle的体系来说,是个观察者(针对Lifecycle),与实际的观察者(针对Lifecycle),两种是职责上的区别,因此,职责是可以同时抗在肩上的。
回顾一下Lifecycle的原理,代码位置如下
当前位置
- LifecycleRegistry.addObserver()
-- ObserverWithState()
--- Lifecycling.getCallback()
static GenericLifecycleObserver getCallback(Object object) {
.....
if (object instanceof GenericLifecycleObserver) {
return (GenericLifecycleObserver) object;
}
.....
}
可见,如果观察者(针对Lifecycle)是GenericLifecycleObserver的话,Event事件是由观察者(针对Lifecycle)自行处理的,此类观察者包揽了以上所述职责。(可以查看Lifecycle体系里的SingleGeneratedAdapterObserver会一目了然,如果都忘了传送门,对于理解很重要)。
当前位置
- LifecycleBoundObserver.onStateChanged()
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
// 检查owner状态
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
// 已销毁移除,避免内存泄漏
removeObserver(mObserver);
return;
}
// 检测观察者是否处于active状态,并作出相应对策
activeStateChanged(shouldBeActive());
}
}
当前位置
- LifecycleBoundObserver. shouldBeActive()
@Override
boolean shouldBeActive() {
// true标示owner至少处于State.STARTED状态
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
不解释
当前位置
- LifecycleBoundObserver. activeStateChanged()
void activeStateChanged(boolean newActive) {
// 同一状态下不做处理
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
// 更新状态
mActive = newActive;
// 是否有处于active状态的观察者
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
1⃣️
if (wasInactive && mActive) {
onActive();
}
2⃣️
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
// 通知数据情况
if (mActive) {
dispatchingValue(this);
}
}
1和2标注部分是指,owner处于State.STARTED、State.RESUMED时观察者为active状态,而State.INITIALIZED、State.CREATED为inActive状态,因此,同种状态下仅做单次回调。
数据通知
当前位置
LifecycleBoundObserver. dispatchingValue()
private 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;
}
这里仅需知道dispatchingValue()会根据观察者的不同,都会尝试通知观察者。
当前位置
- LifecycleBoundObserver. dispatchingValue()
-- considerNotify()
private void considerNotify(ObserverWrapper observer) {
// 观察者处于inActive状态
if (!observer.mActive) {
return;
}
// 源码注释为,检查观察者是否响应此次更改的意义在于,虽然观察者可能
// 处于响应的状态,但此时并没有接收到明确的Event通知,最好不要通知以
// 保持良好的通知秩序
// 这里可以理解为,防止素乱而引起的可能的内存泄漏的问题,也为了保证
// 同一状态下仅做单次通知
if (!observer.shouldBeActive()) {
// 这里回到了触发considerNotify的起点,是为了等待,修复素乱
observer.activeStateChanged(false);
return;
}
// 数据没有更改不做通知
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
// 观察者回调
observer.mObserver.onChanged((T) mData);
}
除了代码中注释处的解释,还要知道的信息是,LiveData拥有私有变量mVersion对持有数据版本做了维护,只有检测到版本更新时才做通知。
此外,在setValue()是也能触发considerNotify()
protected void setValue(T value) {
// 在主线程执行
assertMainThread("setValue");
// 数据版本更新
mVersion++;
mData = value;
// 通知
dispatchingValue(null);
}
分发过程结束,小结如下:
- ObserverWrapper与子类负责持有owner与观察者信息,并实现GenericLifecycleObserver自行处理Event事件
- Event事件到达时,根据owner的State做LiveData做相应处理,在观察者处于active状态时,回调onActive(); 在处于inActive时回调onInactive()
- owner生命周期转变时或更新数据时,LiveData向处于active状态的观察者进行通知
提醒
文章到这里还没有结束,对于LiveData而言,注册防止不仅提供了observe的注册方式,还提供了observeForever的注册方式
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer)
public void observeForever(@NonNull Observer observer)
仅从参数上来看,很容易想到观察者并没有针对指定的onwer进行绑定,从之前的分析来看,在onwer销毁时,观察者也会一并被销毁,因此,此处能联想到,较之Observe的注册方式,observeForever会注册的观察者自身会拥有更广阔的生命周期。
- Adds the given observer to the observers list. This call is similar to * {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which is always active. This means that the given observer will receive all events and will never be automatically removed. You should manually call {@link#removeObserver(Observer)} to stop observing this LiveData.
摘自源码对于observeForever的注释,大意如下:
此方法与observe相似,但是观察者总会收到事件并且不会被自动移除,需要手动移除。
可见,在使用上以及原理处需要做甄别。
案例
public class MainActivity extends AppCompatActivity {
private static final String TAG = "T-MainActivity";
MyData data = BActivity.data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
data.changeValue(data.getValue() + "~");
}
});
findViewById(R.id.startBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, BActivity.class);
startActivity(intent);
}
});
}
}
public class BActivity extends AppCompatActivity {
private static final String TAG = "T-BActivity";
public static MyData data = new MyData();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
data.observeForever(new Observer() {
@Override
public void onChanged(@Nullable String value) {
Log.d(TAG, "I'am still here , value is : " + value);
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}
页面描述:在B页面有LiveData的静态对象,在按下返回键时B会被销毁。Main页面有Click Me按钮,点击时LiveData的数据加上"~"拼接,并有另一个按钮以启动B页面。
页面操作:从Main启动B,按下返回键,多次点击Click Me按钮,日志如下
容易证实,观察者依旧存在。
observeForever原理
public void observeForever(@NonNull Observer observer) {
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
// 除了和observe()类似的检测外,还不能是LifecycleBoundObserver类
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
代码上看,流程是类似的,不过observeForever()并不能使用observe()使用的LifecycleBoundObserver,并且没有通过Lifecycle.LifecycleRegistry进行注册,能猜测通过此方式注册的观察者,并没有和实际的owner进行绑定(之前所说的没有成对出现的情况)。答案会在AlwaysActiveObserver里找到
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
AlwaysActiveObserver很简单,仅有shouldBeActive()方法 ,并且结合之前所述的通过Observe()注册,能知道通过observeForever()注册的观察者性质如下:
- 并没有利用Lifycycle的机制,所以没有对生命周期的感知
- 行为就是简单的观察者模式的简单监听与回调
- 有内存泄漏风险,记得手动移除
简单原理图
图片除了注册过程以及感知过程外,还画出了接收过程,因为理解Lifecycle原理真的对理解很重要
提示
文章到这里就结束了,以下部分为小插曲,感兴趣欢迎阅读
插曲
LiveData的优势在于让数据感知生命周期的变化以及实现数据的共享。在学习LiveData的过程中,有查阅过一些相应的博文,其中让我很关注的地方是,有些地方指出,使用单例让LiveData实现数据共享,并对此不再做必要的解释,很容易引起混淆和误解。
单例只是无可奈何之下的一种形式,是最差解。
LiveData的数据共享的精髓在于利用观察者,而不是利用过长的生命周期。并且,LiveData所要解决的问题是,具有生命周期的组件如何在自身的生命周期里根据必要性的或者重要性的数据状态,来调整自身的状态,并实现生命周期监测与数据状态的解耦。
笔者的呢喃:我都单例了,我都自我共享了,我还需要感知 0 0?
(笔者在中使用了静态对象LiveData仅仅是为了方便展示,实际运用中不要这么干)
在此感谢涂哥的指导和答疑
下一篇:ViewModel