[TOC]
概述
- LiveData 是一個持有數(shù)據(jù)的類祠锣,它持有的數(shù)據(jù)是可以被觀察者訂閱的绒障,當數(shù)據(jù)被修改時就會通知觀察者。觀察者可以是 Activity捂蕴、Fragment、Service 等闪幽。
- LiveData 能夠感知觀察者的生命周期啥辨,只有當觀察者處于激活狀態(tài)(STARTED、RESUMED)才會接收到數(shù)據(jù)更新的通知盯腌,在未激活時會自動解注冊觀察者溉知,以減少內(nèi)存泄漏。
- 使用 LiveData 保存數(shù)據(jù)時腕够,由于數(shù)據(jù)和組件是分離的级乍,當組件重建時可以保證數(shù)據(jù)不會丟失。
優(yōu)點
- 確保 UI 界面始終和數(shù)據(jù)狀態(tài)保持一致帚湘。
- 沒有內(nèi)存泄漏玫荣,觀察者綁定到 Lifecycle 對象并在其相關生命周期 destroyed 后自行解除綁定。
- 不會因為 Activity 停止了而奔潰大诸,如 Activity finish 了捅厂,它就不會收到任何 LiveData 事件了。
- UI 組件只需觀察相關數(shù)據(jù)资柔,不需要停止或恢復觀察焙贷,LiveData 會自動管理這些操作,因為 LiveData 可以感知生命周期狀態(tài)的更改贿堰。
- 在生命周期從非激活狀態(tài)變?yōu)榧せ顮顟B(tài)辙芍,始終保持最新數(shù)據(jù),如后臺 Activity 在返回到前臺后可以立即收到最新數(shù)據(jù)羹与。
- 當配置發(fā)生更改(如屏幕旋轉(zhuǎn))而重建 Activity / Fragment故硅,它會立即收到最新的可用數(shù)據(jù)。
- LiveData 很適合用于組件(Activity / Fragment)之間的通信纵搁。
使用
導入依賴
LiveData 有兩種使用方式吃衅,結(jié)合 ViewModel 使用以及直接繼承 LiveData 類。
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.1.0"
// alternatively, just ViewModel
implementation "android.arch.lifecycle:viewmodel:1.1.0"
// alternatively, just LiveData
implementation "android.arch.lifecycle:livedata:1.1.0"
結(jié)合 ViewModel 使用
LiveData 是一個抽象類诡渴,它的實現(xiàn)子類有 MutableLiveData ,MediatorLiveData。在實際使用中妄辩,用得比較多的是 MutableLiveData惑灵。常常結(jié)合 ViewModel 一起使用。
public class TestViewModel extends ViewModel {
private MutableLiveData<String> mNameEvent = new MutableLiveData<>();
public MutableLiveData<String> getNameEvent() {
return mNameEvent;
}
}
在Activity中創(chuàng)建ViewModel眼耀,監(jiān)聽ViewModel中的數(shù)據(jù)變化
mTestViewModel = ViewModelProviders.of(this).get(TestViewModel.class);
MutableLiveData<String> nameEvent = mTestViewModel.getNameEvent();
nameEvent.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Log.i(TAG, "onChanged: s = " + s);
mTvName.setText(s);
}
});
<font color = "#ff00e0">Activity英支、fragment 數(shù)據(jù)傳遞:</font>
對應activity、viewModel 獲取到的對象是相同的哮伟,所以可用來Activity干花、fragment通信
fragment中:
nameEvent = ViewModelProviders.of(getActivity()).get(HomeFragmentViewModel.class);
nameEvent.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
....
}
});
<font color = "#ff0000">ViewModel 攜帶參數(shù):</font>
? 同樣是調(diào)用 ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) 方法,只不過楞黄,需要多傳遞一個 factory 參數(shù)池凄。
做法:
實現(xiàn) Factory 接口,重寫 create 方法雪侥,在create 方法里面調(diào)用相應的構(gòu)造函數(shù)外臂,返回相應的實例坑律。
public class TestViewModel extends ViewModel {
private final String mKey;
private MutableLiveData<String> mNameEvent = new MutableLiveData<>();
public MutableLiveData<String> getNameEvent() {
return mNameEvent;
}
public TestViewModel(String key) {
mKey = key;
}
public static class Factory implements ViewModelProvider.Factory {
private String mKey;
public Factory(String key) {
mKey = key;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
return (T) new TestViewModel(mKey);
}
}
public String getKey() {
return mKey;
}
}
ViewModelProviders.of(this, new TestViewModel.Factory(mkey)).get(TestViewModel.class)
直接繼承 LiveData 類
以下代碼場景:在 Activity 中監(jiān)聽 Wifi 信號強度。
class WifiLiveData private constructor(context: Context) : LiveData<Int>() {
private var mContext: WeakReference<Context> = WeakReference(context)
companion object {
private var instance: WifiLiveData? = null
fun getInstance(context: Context): WifiLiveData {
if (instance == null) {
instance = WifiLiveData(context)
}
return instance!!
}
}
override fun onActive() {
super.onActive()
registerReceiver()
}
override fun onInactive() {
super.onInactive()
unregisterReceiver()
}
/**
* 注冊廣播尤慰,監(jiān)聽 Wifi 信號強度
*/
private fun registerReceiver() {
val intentFilter = IntentFilter()
intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION)
mContext.get()!!.registerReceiver(mReceiver, intentFilter)
}
/**
* 注銷廣播
*/
private fun unregisterReceiver() {
mContext.get()!!.unregisterReceiver(mReceiver)
}
private val mReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
when (intent.action) {
WifiManager.RSSI_CHANGED_ACTION -> getWifiLevel()
}
}
}
private fun getWifiLevel() {
val wifiManager = mContext.get()!!.applicationContext.getSystemService(android.content.Context.WIFI_SERVICE) as WifiManager
val wifiInfo = wifiManager.connectionInfo
val level = wifiInfo.rssi
instance!!.value = level // 發(fā)送 Wifi 的信號強度給觀察者
}
}
class LiveDataActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
withExtendsLiveDataTest()
}
/**
* 直接繼承 LiveData 類
*/
private fun withExtendsLiveDataTest() {
WifiLiveData.getInstance(this).observe(this, Observer {
Log.e("LiveDataActivity", it.toString()) // 觀察者收到數(shù)據(jù)更新的通知,打印 Wifi 信號強度
})
}
}
當組件(Activity)處于激活狀態(tài)(onActive)時注冊廣播雷蹂,處于非激活狀態(tài)(onInactive)時注銷廣播伟端。
源碼解析
observe 注冊流程
LiveData 通過 observe()
方法將被觀察者 LifecycleOwner
(Activity / Fragment) 和觀察者 Observer 關聯(lián)起來。
LiveData.observe(LifecycleOwner owner , Observer<T> observer)
LiveData源碼:
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// 若 LifecycleOwner 處于 DESTROYED 狀態(tài)匪煌,則返回
return;
}
// LifecycleBoundObserver 把 LifecycleOwner 對象和 Observer 對象包裝在一起
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// mObservers(類似 Map 的容器)的 putIfAbsent() 方法用于判斷容器中的 observer(key)
// 是否已有 wrapper(value)與之關聯(lián)
// 若已關聯(lián)則直接返回關聯(lián)值责蝠,否則關聯(lián)后再返回 wrapper
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;
}
// 由于 LifecycleBoundObserver 實現(xiàn)了 GenericLifecycleObserver 接口,而 GenericLifecycleObserver 又
// 繼承了 LifecycleObserver虐杯,所以 LifecycleBoundObserver 本質(zhì)是一個 LifecycleObserver
// 此處屬于注冊過程玛歌, Lifecycle 添加觀察者 LifecycleObserver
owner.getLifecycle().addObserver(wrapper);
}
感知生命周期變化
由上可知,LifecycleBoundObserver
(LiveData 的內(nèi)部類)是觀察者擎椰,以下具體分析 LifecycleBoundObserver
的實現(xiàn)過程支子。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer); // 保存 Observer
mOwner = owner; // 保存 LifecycleOwner
}
@Override
boolean shouldBeActive() {
// 判斷是否處于激活狀態(tài)
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
// 若 Lifecycle 處于 DESTROYED 狀態(tài),則移除 Observer 對象
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
// 移除觀察者达舒,在這個方法中會移除生命周期監(jiān)聽并且回調(diào) activeStateChanged() 方法
removeObserver(mObserver);
return;
}
// 若處于激活狀態(tài)值朋,則調(diào)用 activeStateChanged() 方法
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
當組件(Activity / Fragment)的生命周期發(fā)生改變時,onStateChanged() 方法將會被調(diào)用巩搏。若當前處于 DESTROYED 狀態(tài)昨登,則會移除觀察者;若當前處于激活狀態(tài)贯底,則會調(diào)用 activeStateChanged() 方法丰辣。activeStateChanged() 方法位于父類 ObserverWrapper 中撒强。
void activeStateChanged(boolean newActive) {
// 若新舊狀態(tài)一致,則返回
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) { // 激活狀態(tài)的 observer 個數(shù)從 0 到 1
onActive(); // 空實現(xiàn)笙什,一般讓子類去重寫
}
if (LiveData.this.mActiveCount == 0 && !mActive) { // 激活狀態(tài)的 observer 個數(shù)從 1 到 0
onInactive(); // 空實現(xiàn)飘哨,一般讓子類去重寫
}
if (mActive) { // 激活狀態(tài),向觀察者發(fā)送 LiveData 的值
dispatchingValue(this);
}
}
分發(fā)Value :dispatchingValue
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
// ...
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
// 循環(huán)遍歷 mObservers 這個 map , 向每一個觀察者都發(fā)送新的數(shù)據(jù)
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
// ...
}
considerNotify
發(fā)送事件:
private void considerNotify(ObserverWrapper observer) {
// ...
observer.mObserver.onChanged((T) mData);
}
上面的 mObserver 正是調(diào)用 observe() 方法時傳入的觀察者琐凭。
更新數(shù)據(jù)方式
setValue
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
dispatchingValue
如上小結(jié)分析的value分發(fā)方法
postValue
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
ArchTaskExecutor
中postToMainThread
方法:
@Override
public void postToMainThread(Runnable runnable) {
//mDelegate是 DefaultTaskExecutor 對象
mDelegate.postToMainThread(runnable);
}
DefaultTaskExecutor
(是TaskExecutor
的實現(xiàn)類)代碼:
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class DefaultTaskExecutor extends TaskExecutor {
private final Object mLock = new Object();
private ExecutorService mDiskIO = Executors.newFixedThreadPool(2);
@Nullable
private volatile Handler mMainHandler;
@Override
public void executeOnDiskIO(Runnable runnable) {
mDiskIO.execute(runnable);
}
//切換到主線程執(zhí)行
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
@Override
public boolean isMainThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}
}
<font color = "#ff00e0">兩種更新方式的區(qū)別:</font>
setValue
:更新數(shù)據(jù)是在調(diào)用setValue
方法所在線程更新postValue
:更新數(shù)據(jù)是在主線程更新