如果你看過了Android架構(gòu)組件之Lifecycle,可以立馬投入到LiveData組件的學(xué)習(xí)中,同樣的,LiveData也是Google I/O 大會(huì)上發(fā)布的架構(gòu)組件,ListData是一個(gè)可被觀察的數(shù)據(jù)持有類,為我們什么需要使用LiveData?主要有以下幾個(gè)有點(diǎn):
更多參考
一,保證數(shù)據(jù)與界面的實(shí)時(shí)更新
LiveData采用了觀察者模式設(shè)計(jì),其中LiveData是被觀察者,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)會(huì)通知觀察者進(jìn)行數(shù)據(jù)更新。通過這點(diǎn),可以確保數(shù)據(jù)和界面的實(shí)時(shí)性。
二,有效避免內(nèi)存泄漏
這是因?yàn)?code>LiveData能夠感知到組件的生命周期,當(dāng)組件狀態(tài)處于DESTROYED狀態(tài)時(shí),觀察者對(duì)象會(huì)被remove。
三,Activity/Fragment銷毀掉時(shí)不會(huì)引起崩潰
這是因?yàn)榻M件處于非激活狀態(tài)時(shí),在界面不會(huì)收到來自LiveData的數(shù)據(jù)變化通知。這樣規(guī)避了很多因?yàn)轫撁驿N毀之后,修改UI導(dǎo)致的crash。
四,不需要手動(dòng)處理生命周期
LiveData能夠感知組件的生命周期,所以設(shè)置LiveData組件的生命周期狀態(tài)。
五,始終能夠保持最新數(shù)據(jù)
生命周期從非活躍狀態(tài)切換到活躍狀態(tài)的時(shí)候,能夠?qū)崟r(shí)的接收最新的數(shù)據(jù)。
六,能夠應(yīng)對(duì)配置更改
由于LiveData保存數(shù)據(jù)的時(shí)候,組件和數(shù)據(jù)是分離的,所以在配置更改(如橫豎屏切換等)的時(shí)候,即便組件被重新創(chuàng)建,因?yàn)閿?shù)據(jù)還保存在LiveData中,這樣也能夠做到實(shí)時(shí)的更新。
七,資源共享
單例模式擴(kuò)展LiveData對(duì)象并包裝成系統(tǒng)服務(wù),以便在應(yīng)用程序中進(jìn)行共享,需要該資源的只需要觀察LiveData即可。
LiveData的使用
通常使用LiveData有三個(gè)步驟:
1,創(chuàng)建LiveData實(shí)例來保存數(shù)據(jù),常常是配合ViewModel一起工作;
2,定義一個(gè)Observer的觀察者對(duì)象,如果有數(shù)據(jù)更新會(huì)通過觀察者的onChanged()方法來同步到UI上面;
3,將觀察者Observer通過observe()方法進(jìn)行綁定。
LiveData有兩種使用方法:一種是直接使用,如接下來的例子;還有一種是繼承LiveData的實(shí)現(xiàn)資源共享的方式。
直接使用的時(shí)候,LiveData一般和ViewModel一起使用。
首先定義個(gè)MyNameViewModel類
class MyNameViewModel : ViewModel() {
// Create a LiveData with a String
private var mCurrentName: MutableLiveData<String>? = null
// Create a LiveData with a String list
private var mNameListData: MutableLiveData<List<String>>? = null
open fun currentName(): MutableLiveData<String> {
if (mCurrentName == null) {
mCurrentName = MutableLiveData()
}
return mCurrentName as MutableLiveData<String>
}
open fun nameList(): MutableLiveData<List<String>> {
if (mNameListData == null) {
mNameListData = MutableLiveData()
}
return mNameListData as MutableLiveData<List<String>>
}
}
class FirstActivity : AppCompatActivity() {
companion object {
val TAG = FirstActivity.javaClass.simpleName
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myNameViewModel = ViewModelProviders.of(this).get(MyNameViewModel::class.java)
myNameViewModel.currentName().observe(this, Observer {
print(it)
})
myNameViewModel.nameList().observe(this, Observer {
if (it != null) {
for (item in it) {
print(item)
}
}
})
}
ViewModel里面,定義兩個(gè)方法,currentName,和nameList兩個(gè)方法,并返回LiveData對(duì)象。然后在activity中通過ViewModelProviders.of(this).get(MyNameViewModel::class.java)拿到viewModel,最后通過observe設(shè)置監(jiān)聽,observe方法里面的兩個(gè)參數(shù)LifecycleOwner owner和Observer<T>,最后在onChanged方法中回調(diào)數(shù)據(jù)(這里kotlin代碼使用的是lamdba表達(dá)式)。
用兩個(gè)按鈕模仿修改ViewModel中保存的LiveData數(shù)據(jù):
btn_change_name.setOnClickListener {
myNameViewModel.currentName().setValue("Hubery")
}
btn_update_list.setOnClickListener {
var nameList = ArrayList<String>()
for (i in 0..9) {
nameList.add("Hubery<$i>")
}
myNameViewModel.nameList().setValue(nameList)
}
現(xiàn)在來看看LiveData資源共享,也就是繼承LiveData的例子:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val mStockManager: StockManager
private val mListener = object : SimplePriceListener() {
fun onPriceChanged(price: BigDecimal) {
setValue(price)
}
}
init {
mStockManager = StockManager(symbol)
}
override fun onActive() {
mStockManager.requestPriceUpdates(mListener)
}
override fun onInactive() {
mStockManager.removeUpdates(mListener)
}
}
當(dāng)LiveData對(duì)象具有活動(dòng)的觀察者時(shí)調(diào)用OnActive方法。LiveData中的數(shù)據(jù)會(huì)調(diào)用setValue方法去更新。
當(dāng)LiveData在沒有任何的Observer監(jiān)聽的時(shí)候,會(huì)調(diào)用Inactive方法,在這里的例子會(huì)removeUpdate方法。
LiveData的原理
借鑒ShymanZhu同學(xué)的關(guān)系圖

LiveData:是LiveData組件里面非常核心的一個(gè)類,主要實(shí)現(xiàn)了observe方法用于注冊(cè)監(jiān)聽,setValue用于主線程設(shè)置值,而postValue子線程和主線程都可以。
MutabeLiveData:繼承了LiveData,LiveData是一個(gè)抽象類不能直接使用,在子類里面重寫了postValue和setValue兩個(gè)方法;
MediatorLiveData:MediatorLiveData繼承了MutabeLiveData;
LifecycleBoundObserver:LifecycleBoundObserver是LiveData的內(nèi)部類,
它繼承了ObserverWrapper并實(shí)現(xiàn)了GenericLifecycleObserver,而這個(gè)GenericLifecycleObserver又實(shí)現(xiàn)了LifecycleObserver,有沒有很熟悉?在Lifecycle組件中通過LifecycleObserver便可以觀察到LifecycleOwner中持有的Lifecycle對(duì)象的生命周期變化。
Observer:LiveData有數(shù)據(jù)更新的時(shí)候就是通過Observer接口的onChanged方法告知界面(Activity,F(xiàn)ragment)。
再次感謝ShymanZhu同學(xué)的時(shí)序圖

上面大致的思路是:在
Fragment中調(diào)用observe()方法的時(shí)候,會(huì)先在方法內(nèi)創(chuàng)建一個(gè)LifecycleBoundObserver對(duì)象,然后通過getLifecycle().addObserver()將這個(gè)創(chuàng)建好的對(duì)象添加進(jìn)去。當(dāng)生命周期會(huì)發(fā)生改變的時(shí)候,會(huì)調(diào)用相應(yīng)的方法,移除觀察者或者通知觀察者更新數(shù)據(jù);另外的調(diào)用LiveData的setValue()、postValue()方法后,也會(huì)通知觀察者更新數(shù)據(jù)。
我們首先根據(jù)上面的思路理一下,首選需要注冊(cè)觀察者,創(chuàng)建LifecycleBoundObserver對(duì)象,生命周期發(fā)生變化之后通知觀察者修改數(shù)據(jù)。
添加觀察者
添加觀察者有兩個(gè)方法可以調(diào)用,observe和observeForever,先來看看這兩個(gè)方法的實(shí)現(xiàn):
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
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);
}
observe方法中需要將LifecycleOwner傳入,而LifecycleOwner的實(shí)現(xiàn)類可以通過getLifecycle(),拿到Lifecycle的生命周期;而observeForever則不需要傳入:
@MainThread
public void observeForever(@NonNull Observer<T> observer) {
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
通過observeForever()添加的觀察者,會(huì)永久收到數(shù)據(jù)變化的回調(diào),除非用戶手動(dòng)removeObserve()觀察者會(huì)一直收到數(shù)據(jù)的變化的回調(diào)通知。
生命周期變化
先看看LifecycleBoundObserver 類的源碼實(shí)現(xiàn):
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);
}
}
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);
}
}
添加了觀察者之后,生命周期發(fā)生改變的時(shí)候就會(huì)調(diào)用onStateChanged()方法,當(dāng)前的狀態(tài)處于DESTROYED的時(shí)候,觀察者會(huì)被remove,當(dāng)當(dāng)前的狀態(tài)為active的時(shí)候,調(diào)用activeStateChanged()方法。
LiveData的數(shù)據(jù)更新
上面我們提到過,LiveData的數(shù)據(jù)更新有兩種方式,第一種就是使用setValue的方式只能在主線程也就是UI線程里面調(diào)用,另外一種就是postValue的方式可以在主線程或者子線程里面調(diào)用。
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);
}
}
setValue和postValue在LiveData中的實(shí)現(xiàn):
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(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);
}
};
通過源碼看到,postValue最后也會(huì)調(diào)用setValue方法,去修改LiveData中的值。