一.简介
LiveData类是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(Activity/Fragment/Service等)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
GitHub:https://developer.android.google.cn/topic/libraries/architecture/livedata
二.基本使用
1.Gradle配置
非androidX项目
implementation "android.arch.lifecycle:extensions:1.1.1"
AndroidX项目
implementation 'androidx.appcompat:appcompat:1.2.0'
这一行依赖,已经可以使用Jetpack的好多组件了,比如ViewModel,比如LiveData等等。当然也可以单个引入,具体见官方文档
Lifecycle | Android 开发者 | Android Developers
2.代码
package com.wjn.rxdemo.livedata;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelStoreOwner;
import com.wjn.rxdemo.R;
public class LiveDataActivity extends AppCompatActivity {
private MutableLiveData<String> mLiveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livedata);
initLiveData();
//主线程更新LiveData setValue()方法
findViewById(R.id.activity_livedata_textview).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mLiveData.setValue("主线程更新LiveData");
Log.d("LiveDataActivity", "通知 LiveData观察者刷新数据 线程----: " + Thread.currentThread().getName());
}
});
//子线程更新LiveData postValue()方法
findViewById(R.id.activity_livedata_nametextview).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
mLiveData.postValue("子线程更新LiveData");
Log.d("LiveDataActivity", "通知 LiveData观察者刷新数据 线程----: " + Thread.currentThread().getName());
}
}).start();
}
});
}
/**
* 初始化LiveData
*/
private void initLiveData() {
mLiveData = new MutableLiveData<>();
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveDataActivity", "LiveData观察者 感知变化 s----: " + s);
Log.d("LiveDataActivity", "LiveData观察者 感知变化 线程----: " + Thread.currentThread().getName());
}
});
}
}
3.结果
模拟主线程更新数据
D/LiveDataActivity: LiveData观察者 感知变化 s----: 主线程更新LiveData
D/LiveDataActivity: LiveData观察者 感知变化 线程----: main
D/LiveDataActivity: 通知 LiveData观察者刷新数据 线程----: main
模拟子线程更新数据
D/LiveDataActivity: 通知 LiveData观察者刷新数据 线程----: Thread-4
D/LiveDataActivity: LiveData观察者 感知变化 s----: 子线程更新LiveData
D/LiveDataActivity: LiveData观察者 感知变化 线程----: main
至此LiveData的最基本的使用就已经完成。下面详细讲解
三.基本讲解
上述讲述了LiveData的最基本的使用。下面对上面的使用做一些讲解。
1. 创建LiveData对象
上述创建LiveData对象使用的是MutableLiveData类。那么为什么不用LiveData类呢。因为LiveData是一个抽象类。而MutableLiveData类继承了LiveData类,并重写了两个更新LiveData的方法。
setValue()方法(主线程更新LiveData)和postValue()方法(子线程更新LiveData)。
2.监听LiveData变化
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveDataActivity", "LiveData观察者 感知变化 s----: " + s);
Log.d("LiveDataActivity", "LiveData观察者 感知变化 线程----: " + Thread.currentThread().getName());
}
});
observe方法传参是两个。
第一个参数:LifecycleOwner拥有类 即Activity/Fragment 这里相当于被观察者 他们在生命周期发生改变时告知观察者。
第二个参数:Observer对象。时这里相当于观察者,监听被观察者的状态。
3.更新LiveData
上述通过两个按钮模拟了主线程和子线程更新LiveData的方法。
也就是
主线程更新LiveData:setValue()方法
mLiveData.setValue("主线程更新LiveData");
子线程更新LiveData:postValue()方法
mLiveData.postValue("子线程更新LiveData");
那么为什么呢?可不可以倒过来呢?
测试一下 子线程使用setValue()方法
new Thread(new Runnable() {
@Oerride
public void run() {
mLiveData.setValue("子线程更新LiveData");
Log.d("LiveDataActivity", "通知 LiveData观察者刷新数据 线程----: " + Thread.currentThread().getName());
}
}).start();
点击按钮发送 报错
com.wjn.rxdemo E/AndroidRuntime: FATAL EXCEPTION: Thread-4
Process: com.wjn.rxdemo, PID: 30432
java.lang.IllegalStateException: Cannot invoke setValue on a background thread
at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:462)
at androidx.lifecycle.LiveData.setValue(LiveData.java:304)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
at com.wjn.rxdemo.livedata.LiveDataActivity$2$1.run(LiveDataActivity.java:39)
at java.lang.Thread.run(Thread.java:929)
显然子线程中更新LiveData中只能使用postValue()方法。
测试一下 主线程使用postValue()方法
mLiveData.postValue("主线程更新LiveData");
点击按钮发送 正常更新
D/LiveDataActivity: 通知 LiveData观察者刷新数据 线程----: main
D/LiveDataActivity: LiveData观察者 感知变化 s----: 主线程更新LiveData
D/LiveDataActivity: LiveData观察者 感知变化 线程----: main
显然主线程中更新LiveData可以使用postValue()方法。
但是 LiveData的更新最好遵循一个原则 原因下面会讲
<1> 主线程中更新LiveData使用setValue()方法。
<2> 子线程中更新LiveData使用postValue()方法。
4.综上:LiveData的基本使用分三个步骤
<1> 创建LiveData对象 使用MutableLiveData类。
<2> 监听LiveData对象 使用observe方法。
<3> 更新LiveData对象 使用setValue()和postValue()方法
四.源码分析
1.创建LiveData对象
MutableLiveData<String> mLiveData = new MutableLiveData<>();
MutableLiveData源码
/**
* {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
*
* @param <T> The type of data hold by this instance
*/
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
继承LiveData抽象类 重写了两个方法postValue()方法和setValue()方法。
2.LiveData对象发送消息
由上可知,发送消息有两个方法。postValue()方法和setValue()方法。
postValue()方法源码
/**
* Posts a task to a main thread to set the given value. So if you have a following code
* executed in the main thread:
* <pre class="prettyprint">
* liveData.postValue("a");
* liveData.setValue("b");
* </pre>
* The value "b" would be set at first and later the main thread would override it with
* the value "a".
* <p>
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
*
* @param value The new value
*/
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
注释
<1> 如果在主线程中 发送两个消息 一个用postValue方法一个用setValue方法。 则先收到b 然后收到a。
验证
发送
mLiveData.postValue("a");
mLiveData.setValue("b");
接收
/**
* 初始化LiveData
*/
private void initLiveData() {
mLiveData = new MutableLiveData<>();
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveDataActivity", "LiveData观察者 感知变化 s----: " + s);
}
});
}
结果
D/LiveDataActivity: LiveData观察者 感知变化 s----: b
D/LiveDataActivity: LiveData观察者 感知变化 s----: a
结论
因为postValue方法是加了同步的,还要切换到主线程执行。所以虽然第一个发送却是最后一个收到。
<2> 如果在主线程执行已提交的任务之前多次调用此方法,则只会分派最后一个值。
验证
发送
mLiveData.postValue("a");
mLiveData.postValue("b");
mLiveData.postValue("c");
接收
/**
* 初始化LiveData
*/
private void initLiveData() {
mLiveData = new MutableLiveData<>();
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveDataActivity", "LiveData观察者 感知变化 s----: " + s);
}
});
}
结果
D/LiveDataActivity: LiveData观察者 感知变化 s----: c
结论
主线程(子线程 经过测试也是一样)中,多次调用postValue方法,只会收到最后一条消息。综上 使用postValue方法连续发送多条数据时只会收到最新的一条数据。原因下面
源码
同步方法中代码
postTask = mPendingData == NOT_SET;
mPendingData = value;
初次进入
因为初始化时 NOT_SET 和mPendingData 两个值如下
static final Object NOT_SET = new Object();
volatile Object mPendingData = NOT_SET;
所以 mPendingData == NOT_SET成立 即 postTask=true。
然后把 传参的value 赋值给 mPendingData。
因为首次进入postTask=true,所以
if (!postTask) {
return;
}
跳过,执行下面的代码
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
将mPostValueRunnable抛到主线程执行。
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);
}
};
同样,在同步方法中将 mPendingData 赋值(postValue方法传入的)给一个重新声明的 Object newValue变量。然后 再次将 NOT_SET赋值给mPendingData 然后调用setValue((T) newValue);方法设置数据 。setValue((T) newValue);方法源码下面讲
到这里首次调用postValue方法的流程就走完了。
再次进入(连续)
同样的流程 因为 mPostValueRunnable源码 中 会再次将 NOT_SET赋值给mPendingData 再次postValue时 postTask属性还是true 还是会执行。
总结
也就是说上述说的连续多次调用postValue方法时,只收到最近一次。但是看源码确实是发送了,至于为什么只收到最后一条。下面讲
setValue()方法源码
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
注释
该方法只能在主线程中 发送消息
验证
assertMainThread("setValue");
private static void assertMainThread(String methodName) {
if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
}
结论
setValue方法,只能在主线程发送消息。因为源码中有检测,不是主线程会抛异常。继续
mVersion++;
mData = value;
版本对应的字段 mVersion+1。然后将setValue方法发送的内容赋值给mData。mVersion字段和mData字段下面会用到。 继续
dispatchingValue(null);
事件分发,这个是最核心的东西。
dispatchingValue方法源码
@SuppressWarnings("WeakerAccess") /* synthetic access */
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;
}
private boolean mDispatchingValue;
mDispatchingValue属性是全局变量默认值false。所以
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
不会执行 跳过。然后立刻将此字段赋值true。
mDispatchingValue = true;
然后 执行 下面的do while循环 多次调用时 如果do while 循环没有执行完 则不会执行。继续
因为 dispatchingValue(null);即 传参null。所以看下面的代码
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
considerNotify(iterator.next().getValue());
继续
considerNotify方法源码
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);
}
首先 参数ObserverWrapper 对象 是添加观察方法是传入的 下面讲 这里先说明一下 这个对象就是LifecycleOwner类的生成类 可以理解为Activity/Fragment等生命周期类。
可以看出
if (!observer.mActive) {
return;
}
如果 Activity/Fragment等生命周期类 状态 本身 就是非活跃的 直接return 结束分发事件。
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
如果 Activity/Fragment等生命周期类 状态 变成 非活跃的 调用observer.activeStateChanged(false);方法 然后直接return 结束分发事件 源码下面讲 继续
if (observer.mLastVersion >= mVersion) {
return;
}
mLastVersion字段:赋值时机
private abstract class ObserverWrapper {
int mLastVersion = START_VERSION;
}
static final int START_VERSION = -1;
也就是说,此字段默认-1。
mVersion字段:赋值时机
private int mVersion = START_VERSION;
但是在setValue()方法中++了。也就是调用了setValue方法后这个字段加1。
所以第一次 两个字段不相同 跳过
observer.mLastVersion = mVersion;
立刻,将mVersion字段赋值给mLastVersion字段字段。
最后
observer.mObserver.onChanged((T) mData);
走到这里,也就调用了onChanged方法。然后添加观察者的onChanged方法就会接收到消息了。
总结
<1> LiveData对象发送消息有两个方法。postValue()方法和setValue()方法。
<2> postValue方法经过同步方法,然后将mPostValueRunnable抛给主线程。最后还是会调用setValue()方法。
<3> setValue()方法中控制两个字段mVersion:版本 和mData:发送的消息。mVersion字段可以控制是否最后执行observer.mObserver.onChanged((T) mData);操作。
<4> considerNotify()方法是整个过程最核心的方法。此方法可以看出,如果当前Activity/Fragment是销毁状态,或者Activity/Fragment变成销毁状态,或者上一次的版本号比本次的大或者等于。都不会最终执行onChanged方法。
3.LiveData对象监听消息(添加观察者方法)
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d("LiveDataActivity", "LiveData观察者 感知变化 s----: " + s);
}
});
observe方法源码
/**
* Adds the given observer to the observers list within the lifespan of the given
* owner. The events are dispatched on the main thread. If LiveData already has data
* set, it will be delivered to the observer.
* <p>
* The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
* or {@link Lifecycle.State#RESUMED} state (active).
* <p>
* If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
* automatically be removed.
* <p>
* When data changes while the {@code owner} is not active, it will not receive any updates.
* If it becomes active again, it will receive the last available data automatically.
* <p>
* LiveData keeps a strong reference to the observer and the owner as long as the
* given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
* the observer & the owner.
* <p>
* If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
* ignores the call.
* <p>
* If the given owner, observer tuple is already in the list, the call is ignored.
* If the observer is already in the list with another owner, LiveData throws an
* {@link IllegalArgumentException}.
*
* @param owner The LifecycleOwner which controls the observer
* @param observer The observer that will receive the events
*/
@MainThread
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);
}
首先,检查线程。如果当前线程不是主线程抛出异常。继续
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
如果,当前LifecycleOwner对象的Lifecycle状态是DESTROYED。即Activity/Fragment处于销毁状态。直接return。不添加观察者方法。继续
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
将LifecycleOwner对象和Observer对象 生成LifecycleBoundObserver对象。继续
LifecycleBoundObserver类源码
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@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(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
可见,LifecycleBoundObserver类 继承 ObserverWrapper类
上面说到的发送消息方法最终走到了核心方法considerNotify方法
该类源码总结
<1> 继承ObserverWrapper类 将传入的observer对象赋值给全局变量 mObserver 这个全局变量就是最后执行
observer.mObserver.onChanged((T) mData);
即发送消息的变量。
<2> shouldBeActive方法,监听最近一次状态。然后这个方法在在considerNotify方法
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
最后,如果没有return observe方法会执行到
owner.getLifecycle().addObserver(wrapper);
即 将LifecycleBoundObserver对象添加观察者。
五.总结
结合源码,总结出LiveData的几个优点。
<1> 优点1
优点:不易发生内存泄漏。不需要手动解除观察,开发者不需要在onPause或onDestroy方法中解除对LiveData的观察。
原因:observer会在LifecycleOwner状态变为DESTROYED后自动remove。
源码解析:添加观察者时 observe方法中 生成LifecycleBoundObserver对象时 LifecycleBoundObserver类中有一个onStateChanged方法 判断生命周期组件处于DESTROYED状态时会移除Observer对象。具体看上述源码讲解。
<2> 优点2
优点:不会因Activity/Fragment停止而导致崩溃。
原因:如果LifecycleOwner生命周期处于非活跃状态,则它不会接收任何LiveData事件。
源码解析:添加观察者时 observe方法中 会判断生命周期组件处于DESTROYED状态时 如果是 直接return。不会发生消息,所以这种状态也就收不到消息,接收消息的逻辑也不会执行,所以不会因为Activity/Fragment被销毁而崩溃 具体看上述源码讲解。
<3> 优点3
优点:数据始终保持最新状态。
原因:数据更新时 若LifecycleOwner为非活跃状态,那么会在变为活跃时接收最新数据。
源码解析:添加观察者时 observe方法中 生成LifecycleBoundObserver对象时 LifecycleBoundObserver类中有一个onStateChanged方法 该方法会在最后一行执行activeStateChanged(shouldBeActive());方法。
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
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.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
最后执行到dispatchingValue方法
void dispatchingValue(@Nullable ObserverWrapper initiator) {
}
而dispatchingValue方法最执行considerNotify方法。considerNotify方法源码上面有的。