1、简介
同时具有观察者身份和被观察者身份的组件、LiveData数据的改变,可以监听到其的变化。用数据驱动的思想替换了常规接口回调的方式。
2、使用
- 简单的使用
(1)创建一个LiveData
/**
* author : weishixiong
* e-mail : weishixiong@pudutech.com
* date : 2022/2/22 10:48
* desc :单例MyLiveData
*/
object MyLiveData {
val data = MutableLiveData<String>()
}
(2)改变并监听其数据的变化
class MainActivity : AppCompatActivity() {
val TAG = javaClass.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MyLiveData.data.observe(this, object : Observer<String> {
override fun onChanged(t: String?) {
Log.e(TAG, "onChanged:${Thread.currentThread().name} and ${t}")
}
})
MyLiveData.data.postValue("hello world")
class MainActivity : AppCompatActivity() {
val TAG = javaClass.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MyLiveData.data.observe(this, object : Observer<String> {
override fun onChanged(t: String?) {
Log.e(TAG, "onChanged:${Thread.currentThread().name} and ${t}")
}
})
MyLiveData.data.value = "hello "
thread {
MyLiveData.data.postValue("world")
}
}
}
com.example.lifecycle E/MainActivity: onChanged:main and hello
com.example.lifecycle E/MainActivity: onChanged:main and world
- setValue和postValue的区别
(1)setValue只能在主线程调用
(2)postValue既能在主线程调用,也能在子线程调用,如果需要在子线程调用改变LiveData的数据,使用postValue
(3)postValue最终也是调用到setValue方法,通过Handler线程切换到主线程,然后在主线程调用setValue
如下源码体现:
调用postValue方法,在postValue方法中调用postToMainThread方法
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
在postToMainThread方法中,拿到主线程的Looper设置给Handler,在调用 mMainHandler.post(runnable);
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
在Runnable中执行setValue方法
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
}
- LiveData的粘性事件
通常在使用LiveData的使用,我们都是先调用observe方法订阅,然后再改变数据。
但是假如我们先改变数据,然后再订阅,其实也是能收到数据的变化,这种现象称之为粘性事件,这并不是一个BUG,而是LiveData的特性。
例如:我们再MainActivity1中先对LiveData的值进行改变,然后再跳转到MainActivity2订阅LiveData,来看看现象
MyLiveData.data.value = "hello world"
findViewById<TextView>(R.id.tv_click).setOnClickListener {
startActivity(Intent(this, Main2Activity::class.java))
}
class Main2Activity : AppCompatActivity() {
val TAG = javaClass.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MyLiveData.data.observe(this, object : Observer<String> {
override fun onChanged(t: String?) {
Log.e(TAG, "onChanged:${Thread.currentThread().name} and ${t}")
}
})
}
}
Main2Activity: onChanged:main and hello world
我们看到在Main2Activity 依然能收到LiveData变化之后的数据。在后面源码分析我们将分析为什么?
3、源码简单分析
- LiveData的注册
调用LiveData的observe进行注册,并传入当前Activity的实例this,和Observe的实现类,重写onChanged函数
MyLiveData.data.observe(this, object : Observer<String> {
override fun onChanged(t: String?) {
Log.e(TAG, "onChanged:${Thread.currentThread().name} and ${t}")
}
})
在observe方法中,首先将我们的宿主和observer包装成一个LifecycleBoundObserver,而LifecycleBoundObserver实现了LifecycleEventObserver接口并继承了ObserverWrapper类,这样一来LifecycleBoundObserver就可以监听宿主Activity的生命周期并持有了observer对象。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
//创建LifecycleBoundObserver 监听宿主的生命周期,并持有observer对象
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//同时将LifecycleBoundObserver存入到一个map中。
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);
}
同时调用了putIfAbsent 将LifecycleBoundObserver 对象存到一个map中。然后调用addObserver,将LifecycleBoundObserver 关联到宿主Activity中,监听其生命周期。
以上代码小结:LiveData调用observe方法注册的时候,主要做了两个工作
(1)创建一个LifecycleBoundObserver对象,并持有observer。监听宿主Activity的生命周期
(2)将LifecycleBoundObserver存到一个map中
- 设置LiveData的数据
通过使用setValue和postValue方法设置LiveData的数据,最终都会调用到setValue这话方法,
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
在setValue方法中对mVersion成员变量+1,这个变量很关键,通过这个变量来判断LiveData数据是否改变了。然后再setValue方法中调用dispatchingValue方法,意思就是将改变之后的数据分发出去。dispatchingValue方法如下:
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<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
由于dispatchingValue方法传的参数为null,所有会走到else中去,接着遍历之前存到map中的LifecycleBoundObserver对象,调用considerNotify函数
@SuppressWarnings("unchecked")
private void considerNotify(ObserverWrapper observer) {
//判断是否可见
if (!observer.mActive) {
return;
}
//判断是否可见
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
然后回调observer中的onChanged方法。而在调用onChanged方法之前主要做了两个判断:
(1)通过LifecycleBoundObserver监听Activity的生命周期,调用shouldBeActive函数和mActive属性,判断Activity是否可见,如果不可见直接return,所以当我们的Activity是不可见的时候,是监听不到数据的变化的。
如果需要不可见的时候也监听数据的变化可以采用observeForever
(2)判断LifecycleBoundObserver中持有的版本mLastVersion 是否小于LiveData的版本,如果小于,所以mVersion有做过++,因为我们在setValue的时候,有对mVersion+1操作。
在初始化的时候mVersion和mLastVersion的版本都为-1。当mVersion+1之后,mVersion版本>LifecycleBoundObserver中mLastVersion 的版本。说明有数据改变,所以直接回调onChanged函数。接着对齐版本,将mVersion的值,赋值给mLastVersion。
在上面我们可以看到主要通过dispatchingValue这个函数,将数据分发出去,然后回调我们的onChanged函数
那为什么数据会粘性呢?
我们来观察调用dispatchingValue的地方,除了LiveData设置数据的时候主动触发,同时在Activity生命周期变化的时候,也会触发。我们来看下代码
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
}
我们看到LifecycleBoundObserver 通过onStateChanged函数监听宿主Activity的生命周期,然后调用ObserverWrapper 中的activeStateChanged方法,在activeStateChanged方法中调用dispatchingValue分发数据。此时dispatchingValue方法的传参,传了this。也就是LifecycleBoundObserver 对象。
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<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
这样就触发dispatchingValue方法中的if部分,调用 considerNotify(initiator);在considerNotify中的操作就一样了,同样是先判断版本,如果当前版本大于LifecycleBoundObserver 中的版本,就回调onChanged函数。
而由于在调用MainActivity1中调用setValue的时候,我们将mVersion++,所以mVersion的版本是>mLastVersion的。所以就会回调onChanged,MainActivity2就能收到LiveData数据的变化,这样就被称为了粘性事件。
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
- 通过一张图大概分析LiveData的工作原理
总结
- LiveData不管是通过post还是set,最终都是通过setValue改变数据
- LiveData监听数据的变化主要通过当前版本mVersion和LifecycleBoundObserver 持有的版本进行比较。
- LiveData持有了一个LifecycleBoundObserver 对象,主要是用于监听Activity的生命周期,持有一个observer作为观察者,观察LiveData的数据变化。变化的时候通过observer的onChanged函数
- 触发onChanged方法,也就是监听到数据变化的时候,主要有两个途径
(1)当调用LiveData的setValue方法的时候mVersion+1,然后主动去回调observer的onChanged方法,回调该方法之前判断版本和Activity是否可见,都满足的时候才调用。如果不满足,直接rerurn,不做处理。
(2)当LifecycleBoundObserver 监听到Activity生命周期为可见的时候,同样按照上述步骤1判断版本号,决定是否回调onChanged方法。这也是粘性数据的根本原因,如果启动第二个Activity的时候,发现版本大于LifecycleBoundObserver 持有的版本,则说明数据有变化。回调onChanged方法