1 前言
簡單的說,LiveData是一個資料持有類,持有的資料可被觀察者觀察。它具有以下特點
- 資料可以被觀察者訂閱;
- 能夠感覺元件(Fragment、Activity、Service)的生命周期;
- 隻有在元件出于激活狀态(STARTED、RESUMED)才會通知觀察者有資料更新;
當然這裡的元件都是指實作了LifecycleOwner接口的元件。
官方推薦我們使用LiveData時結合ViewModel來使用,進而達到解耦的目的。那麼為什麼需要使用LiveData呢?或者說,使用LiveData能給我們帶來什麼好處呢?
2 LiveData的功能
從官方文檔來看,LiveData的使用有以下幾大好處
- 保證UI狀态和資料的統一
LiveData采用了觀察者設計模式。當生命周期狀态改變時,LiveData會通知Observer對象。每次應用程式資料更改時,都會通知觀察者對象,進而更新UI。
- 減少記憶體洩漏
LiveData能夠感覺到元件的生命周期,觀察者綁定到生命周期對象,并在其相關生命周期被破壞後自行清理。
- 當Activity停止時不會引起崩潰
這是因為元件處于非激活狀态時,不會收到LiveData中資料變化的通知
- 不需要額外的手動處理來響應生命周期的變化
這一點同樣是因為LiveData能夠感覺元件的生命周期,是以就完全不需要在代碼中告訴LiveData元件的生命周期狀态。
- 元件和資料相關的内容能實時更新
元件在前台的時候能夠實時收到資料改變的通知,這是可以了解的。當元件從背景到前台來時,LiveData能夠将最新的資料通知元件,這兩點就保證了元件中和資料相關的内容能夠實時更新。
- 針對configuration change時,不需要額外的處理來儲存資料
我們知道,當你把資料存儲在元件中時,當configuration change(比如語言、螢幕方向變化)時,元件會被recreate,然而系統并不能保證你的資料能夠被恢複的。當我們采用LiveData儲存資料時(結合ViewModel),因為資料群組件分離了。當元件被recreate,資料還是存在LiveData中,并不會被銷毀。
- 資源共享
通過繼承LiveData類,然後将該類定義成單例模式,在該類封裝監聽一些系統屬性變化,然後通知LiveData的觀察者,例如下面的例子
/**
* @author Created by qiyei2015 on 2018/2/25.
* @version: 1.0
* @email: [email protected]
* @description: 監聽網絡是否連接配接的LiveData
*/
public class NetworkLiveData extends LiveData<Integer> {
private static NetworkLiveData sNetworkLiveData;
private WeakReference<Context> mContextWeakReference;
private NetworkChangeReceiver mChangeReceiver;
private NetworkLiveData(Context context){
mContextWeakReference = new WeakReference<Context>(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 = , mobile = , none = ;
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<Integer>() {
@Override
public void onChanged(@Nullable Integer networkState) {
//your code
}
});
注意,這裡我們并沒有顯式在Activity/Fragment 中移除LiveData的監聽,因為LiveData可以自動的幫我們處理這個過程
3 LiveData類圖
LiveData的類圖如下:
可以看到,主要涉及到的類就是LiveData,MutableLiveData,LifecycleBoundObserver,Observer。其他的類已在LifeCycle中介紹過了。
我們先來看LiveData
LiveData< T >是一個抽象的泛型類,主要提供以下幾個方法
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)//添加觀察者
@MainThread
public void observeForever(@NonNull Observer<T> observer)//添加永久的觀察者,不考慮是否處于激活狀态
@MainThread
public void removeObserver(@NonNull final Observer<T> 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<T> observer;
public boolean active;
public int lastVersion = START_VERSION;
LifecycleBoundObserver(LifecycleOwner owner, Observer<T> 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 == ;
LiveData.this.mActiveCount += active ? : -;
if (wasInactive && active) {
onActive();
}
if (LiveData.this.mActiveCount == && !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 元件解析
4 LiveData解析
LiveData我覺得弄清楚以下幾個問題就可以了。
1 LiveData如何添加觀察者?
我們直接從observe(@NonNull LifecycleOwner owner, @NonNull Observer< T> observer)開始分析
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> 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
實際上調用的是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 != || mHandlingEvent;
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) <
&& 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<T> observer;
public boolean active;
public int lastVersion = START_VERSION;
LifecycleBoundObserver(LifecycleOwner owner, Observer<T> 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 == ;
LiveData.this.mActiveCount += active ? : -;
if (wasInactive && active) {
onActive();
}
if (LiveData.this.mActiveCount == && !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的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