JetPack 之 LiveData

LiveData是一个可以感知Activity、Fragment生命周期的数据容器。当LiveData所持有的数据发生改变时,它会通知相应的观察者进行数据更新。由于Activity、Fragment都已实现LifecycleOwner接口,所以持有LifecycleOwner引用的LiveDataLifecycleOwner的生命周期处于startedpaused时可以作出相应更新,而在LifecycleOwner处于被销毁时停止更新。

LiveData 的优点

  • 保证UI状态和数据的统一
    LiveData采用了观察者设计模式。当生命周期状态改变时,LiveData会通知Observer对象。每次应用程序数据更改时,都会通知观察者对象,从而更新UI。
  • 减少内存泄漏
    LiveData能够感知到组件的生命周期,观察者绑定到生命周期对象,并在其相关生命周期被破坏后自行清理。
  • 当Activity停止时不会引起崩溃
    这是因为组件处于非激活状态时,不会收到LiveData中数据变化的通知
  • 不需要额外的手动处理来响应生命周期的变化
    这一点同样是因为LiveData能够感知组件的生命周期,所以就完全不需要在代码中告诉LiveData组件的生命周期状态。
  • 组件和数据相关的内容能实时更新
    组件在前台的时候能够实时收到数据改变的通知,这是可以理解的。当组件从后台到前台来时,LiveData能够将最新的数据通知组件,这两点就保证了组件中和数据相关的内容能够实时更新。
  • 资源共享
    通过继承LiveData类,然后将该类定义成单例模式,在该类封装监听一些系统属性变化,然后通知LiveData的观察者

实例

使用Android的LiveData,需要在gradle添加引用:

1
2
3
compile "android.arch.lifecycle:runtime:1.1.1'"
compile "android.arch.lifecycle:extensions:1.1.1'"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1'"

LiveData的代码比较简单,我们根据代码来了解其工作原理。我定义一个NetWorkState类,这个类的功能是对网络状态的广播进行监听。在onActive方法中注册广播,在onInactive取消广播,收到广播通知之后执行setValue将实例的值修改为当前网络状态并通知观察者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class NetWorkState(val context: Context) : LiveData<Boolean>() {
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
value = NetworkUtils.isConnected()
}
}
override fun onInactive() {
super.onInactive()
context.unregisterReceiver(broadcastReceiver)
}
override fun onActive() {
super.onActive()
val intentFilter = IntentFilter()
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
context.registerReceiver(broadcastReceiver, intentFilter)
}
}

LiveData包含4个重要的方法:

  • onActive():当LiveData被激活时调用
  • onInactive():当LiveData被取消时调用
  • setValue(T):更新LiveData所持有的数据并通知观察者,必须在主线程调用
  • postValue(T):与setValue(T)一样,不过可以在子线程中调用

LiveData使用起来很简单,直接初始化好LiveData对象之后,调用observe方法将其绑定在当前Activity的LifecycleOwner上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class LiveDataActivity : AppCompatActivity() {
val state: NetWorkState by lazy {
NetWorkState(applicationContext)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DataBindingUtil.setContentView<ActivityLivedataBinding>(this, R.layout.activity_livedata)
state.observe(this, Observer<Boolean> {
Toast.makeText(this, if (it) "网络连接成功" else "网络连接失败", Toast.LENGTH_LONG).show()
})
}
}

LiveData的实现原理

我们可以通过observe()源码方法入手来了解一下LiveData生命周期绑定的流程 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// 如果owner处在DESTROYED的环节,则直接忽略
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);
}

如果owner的声明周期处在DESTROYED的环节,则直接退出。在其他生命周期环节下,LiveData根据owner和observer构造LifecycleBoundObserver对象wrapper,首先检查mObservers是否已经添加了这个observer,如果重复添加会报异常,否则将其添加到mObservers。随后通过owner.getLifecycle().addObserver(wrapper)将其与Lifecycle进行绑定。

owner.getLifecycle().addObserver(wrapper)实际上调用的是Activity/Fragment中的mLifecycleRegistry来添加观察者,最终会调用到LifecycleRegistry中的addObserver(@NonNull LifecycleObserver observer)。这样Activity/Fragment的生命周期变化回调到LifecycleBoundObserver。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<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并实现了GenericLifecycleObserver接口。当Activity/Fragment的生命周期变化会回调LifecycleBoundObserver.onStateChanged。如果owner处于DESTROYED,那么就移除当前组件Lifecycle绑定关系。反之则调用activeStateChanged(boolean newActive)。之前我们实现的onActive()与onInactive()全凭它控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
}
}

进入activeStateChanged(),首先判断当前的状态是否和上一次一致,一致则方法不执行。其次计算当前mActiveCount的数量,如果LiveData从未被激活过,则调用onActive()方法。因为多个activity有可能共享同一个LiveData,所以这里加入了mActiveCount计数。只要没有一个LiveData被激活,则回调onInactive()。当LiveData被重新激活后,就会执行dispatchingValue()来检查并处理之前没有发出去的通知,然后执行considerNotify()调用观察者的onChanged()将数据发送出去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
}

首先要满足mActive为true,这个值改变渠道有2个地方:

  • LiveData中组件绑定Lifecycle的时候,此时会将该值通过activeStateChanged()设置为true,解绑的时候设置为false;
  • 在owner的生命周期发生改变的情况下,生命周期至少在onStart和onPause之间的时候设置为true,其他情况下为false。这就意味着只有在onStart和onPause之间发出的通知才可以立即收到。那onPause之后且未发生onDestory这段时期的通知=会被存在mData,但是也只能存最后一条通知。

从源码中可以看到,发送数据前还会检查数据版本号,由于每次执行setValue()或者postValue的时候,mVersion都会自增1,所以当你发出多个通知的时候,只有最后一条才会满足observer.mLastVersion >= mVersion,因此也不用担心多条通知并发而产生的时序性问题。

MutableLiveData

LiveData中的setValue()与postValue是封装在其内部使用的,MutableLiveData只是将它拿出来,方便我们在外界使用,源码如下:

1
2
3
4
5
6
7
8
9
10
11
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);
}
}

MediatorLiveData

MediatorLiveData继承于MutableLiveData,可以同时监听多个LiveData,它提供了addSource()removeSource()添加和删除LiveData。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
e.plug();
}
}
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}

MediatorLiveData比较特别的地方在于可以给它随时增加或删除一个LiveData,你可以让其中任何一个LiveData发送通知给MediatorLiveData。

参考文章