简单的说,LiveData是一个数据持有类,持有的数据可被观察者观察。它具有以下特点
当然这里的组件都是指实现了LifecycleOwner接口的组件。
官方推荐我们使用LiveData时结合ViewModel来使用,从而达到解耦的目的。那么为什么需要使用LiveData呢?或者说,使用LiveData能给我们带来什么好处呢?
从官方文档来看,LiveData的使用有以下几大好处
LiveData采用了观察者设计模式。当生命周期状态改变时,LiveData会通知Observer对象。每次应用程序数据更改时,都会通知观察者对象,从而更新UI。
LiveData能够感知到组件的生命周期,观察者绑定到生命周期对象,并在其相关生命周期被破坏后自行清理。
这是因为组件处于非激活状态时,不会收到LiveData中数据变化的通知
这一点同样是因为LiveData能够感知组件的生命周期,所以就完全不需要在代码中告诉LiveData组件的生命周期状态。
组件在前台的时候能够实时收到数据改变的通知,这是可以理解的。当组件从后台到前台来时,LiveData能够将最新的数据通知组件,这两点就保证了组件中和数据相关的内容能够实时更新。
我们知道,当你把数据存储在组件中时,当configuration change(比如语言、屏幕方向变化)时,组件会被recreate,然而系统并不能保证你的数据能够被恢复的。当我们采用LiveData保存数据时(结合ViewModel),因为数据和组件分离了。当组件被recreate,数据还是存在LiveData中,并不会被销毁。
通过继承LiveData类,然后将该类定义成单例模式,在该类封装监听一些系统属性变化,然后通知LiveData的观察者,例如下面的例子
/**
* @author Created by qiyei2015 on 2018/2/25.
* @version: 1.0
* @email: 1273482124@qq.com
* @description: 监听网络是否连接的LiveData
*/
public class NetworkLiveData extends LiveData<Integer> {
private static NetworkLiveData sNetworkLiveData;
private WeakReference mContextWeakReference;
private NetworkChangeReceiver mChangeReceiver;
private NetworkLiveData(Context context){
mContextWeakReference = new WeakReference(context);
}
/**
* DCL 方式单例
* @return
*/
public static NetworkLiveData getInstance(Context context){
if (sNetworkLiveData == null){
synchronized (NetworkLiveData.class){
if (sNetworkLiveData == null){
sNetworkLiveData = new NetworkLiveData(context);
}
}
}
return sNetworkLiveData;
}
/**
* observer 从0 到1 调用
*/
@Override
protected void onActive() {
super.onActive();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
mChangeReceiver = new NetworkChangeReceiver();
mContextWeakReference.get().registerReceiver(mChangeReceiver, filter);
}
/**
* observer 从1 到0 调用
*/
@Override
protected void onInactive() {
super.onInactive();
mContextWeakReference.get().unregisterReceiver(mChangeReceiver);
}
/**
* 网络状态变更的广播
*/
private class NetworkChangeReceiver extends BroadcastReceiver {
public final int wifi = 2, mobile = 1, none = 0;
public int oldState = none;
/**
* 触发网络状态监听回调
*
* @param nowStatus 当前网络状态
*/
private void setChange(int nowStatus) {
oldState = nowStatus;
sNetworkLiveData.setValue(oldState);
}
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mobNetInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo wifiNetInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (!mobNetInfo.isConnected() && !wifiNetInfo.isConnected()) {
Log.i("通知", "网络不可以用");
setChange(none);
} else if (mobNetInfo.isConnected()) {
Log.i("通知", "仅移动网络可用");
setChange(mobile);
} else if (wifiNetInfo.isConnected()) {
Log.i("通知", "Wifi网络可用");
setChange(wifi);
}
}
}
}
其中
onActive(),此方法是当处于激活状态的observer个数从0到1时,该方法会被调用。
onInactive() ,此方法是当处于激活状态的observer个数从1变为0时,该方法会被调用。
这样子,在任何Activity/Fragment中我们都可以使用如下方式来观察网络状态变化
NetworkLiveData.getInstance(this).observe(this, new Observer() {
@Override
public void onChanged(@Nullable Integer networkState) {
//your code
}
});
注意,这里我们并没有显式在Activity/Fragment 中移除LiveData的监听,因为LiveData可以自动的帮我们处理这个过程
LiveData的类图如下:
可以看到,主要涉及到的类就是LiveData,MutableLiveData,LifecycleBoundObserver,Observer。其他的类已在LifeCycle中介绍过了。
我们先来看LiveData
LiveData< T >是一个抽象的泛型类,主要提供以下几个方法
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer)//添加观察者
@MainThread
public void observeForever(@NonNull Observer observer)//添加永久的观察者,不考虑是否处于激活状态
@MainThread
public void removeObserver(@NonNull final Observer observer)//移除观察者
@MainThread
public void removeObservers(@NonNull final LifecycleOwner owner)//移除被观察的对象
@Nullable
public T getValue()//获取持有的数据
public boolean hasObservers()//是否有观察者
public boolean hasActiveObservers()//是否有活跃的观察者
MutableLiveData
MutableLiveData继承自LiveData,源码如下,主要将postValue和setValue设置为Public。
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);
}
}
LifecycleBoundObserver
LifecycleBoundObserver是LiveData的内部类,实现于GenericLifecycleObserver接口,该接口又继承LifecycleObserver接口,主要用于LiveData添加观察者时,包装LifecycleOwner和Observer使用
class LifecycleBoundObserver implements GenericLifecycleObserver {
public final LifecycleOwner owner;
public final Observer observer;
public boolean active;
public int lastVersion = START_VERSION;
LifecycleBoundObserver(LifecycleOwner owner, Observer observer) {
this.owner = owner;
this.observer = observer;
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(observer);
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
}
void activeStateChanged(boolean newActive) {
if (newActive == active) {
return;
}
active = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += active ? 1 : -1;
if (wasInactive && active) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !active) {
onInactive();
}
if (active) {
dispatchingValue(this);
}
}
}
根据前面的分析,Activity/Fragment均实现了LifecycleOwner接口,并且当Activity/Fragment 生命周期变化时会发送相应的事件到LifecycleObserver的实例,因此,当Activity/Fragment生命周期变化时,最终会回调到LifecycleBoundObserver 的onStateChanged(LifecycleOwner source, Lifecycle.Event event)方法。关于这一点可以参考
Android架构组件二 Android Architecture Components Lifecycles 组件解析
LiveData我觉得弄清楚以下几个问题就可以了。
1 LiveData如何添加观察者?
我们直接从observe(@NonNull LifecycleOwner owner, @NonNull Observer< T> observer)开始分析
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
LifecycleBoundObserver existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing.owner != wrapper.owner) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
首先根据LifecycleOwner 和Observer构造LifecycleBoundObserver 对象wrapper,然后将其添加到SafeIterableMap
owner.getLifecycle().addObserver(wrapper);
实际上调用的是Activity/Fragment 中的LifecycleRegistry mLifecycleRegistry来添加观察者,最终会调用到LifecycleRegistry中的addObserver(@NonNull LifecycleObserver observer)
LifecycleRegistry.java
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if (previous != null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter--;
}
这样,最终Activity/Fragment的生命周期变化会被LifecycleBoundObserver 观察到,这个和我们上面的分析一致。
同理LiveData的removeObserver(@NonNull final Observer< T> observer)逻辑也类似。最终会在LifecycleRegistry 中移除对Activity/Fragment的观察。
这样,添加和移除观察者的逻辑就理清楚了。
2 LiveData如何感知组件生命周期?
根据前面的分析,当LifecycleOwner的实现者Activity/Fragment 的生命周期变化,由于添加了LifecycleBoundObserver,因此最终会回调到LifecycleBoundObserver#onStateChanged(LifecycleOwner source, Lifecycle.Event event)方法
class LifecycleBoundObserver implements GenericLifecycleObserver {
public final LifecycleOwner owner;
public final Observer observer;
public boolean active;
public int lastVersion = START_VERSION;
LifecycleBoundObserver(LifecycleOwner owner, Observer observer) {
this.owner = owner;
this.observer = observer;
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(observer);
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
}
void activeStateChanged(boolean newActive) {
if (newActive == active) {
return;
}
active = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += active ? 1 : -1;
if (wasInactive && active) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !active) {
onInactive();
}
if (active) {
dispatchingValue(this);
}
}
}
可以看到onStateChanged(LifecycleOwner source, Lifecycle.Event event)的逻辑如下:
1 首先判断LifecycleOwner 的状态时候是DESTROYED,如果是直接移除观察者,这样就帮我们在LifecycleOwner 中移除了观察者,减少了很多重复性的代码
2 判断LifecycleOwner 的状态是否是Active,并根据mActiveCount Observer 的个数和Active状态开始回调onActive()或者onInactive()方法
3 如果activeStateChanged(boolean newActive)中判断到LifecycleOwner 的状态是Active,就调用dispatchingValue(this);进行数据的分发。最终会调用到LiveData的如下方法
private void considerNotify(LifecycleBoundObserver observer) {
if (!observer.active) {
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 (!isActiveState(observer.owner.getLifecycle().getCurrentState())) {
observer.activeStateChanged(false);
return;
}
if (observer.lastVersion >= mVersion) {
return;
}
observer.lastVersion = mVersion;
//noinspection unchecked
observer.observer.onChanged((T) mData);
}
首先会判断LifecycleOwner是否处于前台,然后会调用
observer.observer.onChanged((T) mData);
这样子会调用到Observer的onChanged(@Nullable T t)方法。
这样子就解释了为什么LifecycleOwner只有在前台才会收到数据更新。
有关LiveData的分析就暂时结束了,有关Android架构组件的分析也告一段落了,关于Room数据库组件暂时还没有用到。后续再写文章分析吧。
参考:
https://developer.android.google.cn/topic/libraries/architecture/livedata.html
https://shymanzhu.com/2017/12/23/Android%E6%9E%B6%E6%9E%84%E7%BB%84%E4%BB%B6%EF%BC%88%E4%BA%8C%EF%BC%89%E2%80%94%E2%80%94LiveData/#more