前言
最近在學(xué)習(xí) Google 推出的框架Jetpack,雖然目前網(wǎng)上的資料已經(jīng)很多了,但為了加深印象和邊動(dòng)手練習(xí)跟著學(xué)習(xí),所以站在了下面的巨人的肩膀上,并根據(jù)當(dāng)前最新的API 和編寫實(shí)際Demo,記錄下一些學(xué)習(xí)筆記,大部分是參考巨人們的,整理和休整,加入自己理解和更新吧,學(xué)習(xí)領(lǐng)略了Android Jetpack組件的一點(diǎn)魅力
目前學(xué)習(xí)筆記系列為:
- Android Jetpack 之 Lifecycles ---入門使用
- Android Jetpack 之 LiveData---入門使用
- Android Jetpack 之 Room ---入門使用
- Android Jetpack 之 WorkManger---入門使用
- ....待續(xù)
日常鳴謝巨人
正題
LiveData 簡介
- LiveData是一個(gè)具有生命周期感知特性的可觀察的數(shù)據(jù)保持類,使用LiveData保存數(shù)據(jù)時(shí),在每次訂閱或數(shù)據(jù)更新時(shí)會(huì)自動(dòng)回調(diào)設(shè)置的觀察者從而更新數(shù)據(jù),真正的實(shí)現(xiàn)了數(shù)據(jù)驅(qū)動(dòng)的效果
- LiveData的創(chuàng)建基本會(huì)在ViewModel中,從而使數(shù)據(jù)在界面銷毀時(shí)繼續(xù)保持
- LiveData 認(rèn)為觀察者的生命周期處于STARTED狀態(tài)或RESUMED狀態(tài)下,表示觀察者處于活動(dòng)狀態(tài),LiveData只通知活躍的觀察者更新數(shù)據(jù)
- 注冊一個(gè)實(shí)現(xiàn)該LifecycleOwner 接口的對象配對的觀察者,當(dāng)相應(yīng)Lifecycle對象的狀態(tài)改變?yōu)镈ESTROYED時(shí)需移除觀察者
LiveData 的簡單使用
依賴添加
def lifecycle_version = "2.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation 'android.arch.lifecycle:extensions:1.1.1'
創(chuàng)建一個(gè)LiveData實(shí)例來保存某種類型的數(shù)據(jù)
class TestViewModel : ViewModel() {
var mCurrent: MutableLiveData<String>? = null
get() {
if (field == null) {
field = MutableLiveData()
}
return field
}
}
確保存儲(chǔ)LiveData對象是在ViewModel中而不 是Activity 或 Fragment 中
創(chuàng)建一個(gè)定義onChanged()方法的Observer對象,在數(shù)據(jù)變化時(shí)回調(diào)
// 創(chuàng)建觀察者對象
val nameObservable = Observer<String> {
ld_tv.text = it // onChange() 方法中的操作
}
使用observe() 方法將觀察者對象附加到LiveData對象,這將觀察對象向LiveData對象訂閱,以便通知其更改
// 創(chuàng)建viewModel 對象
mModel = ViewModelProviders.of(this).get(TestViewModel::class.java)
// mCurrent 訂閱觀察
mModel.mCurrent!!.observe(this,nameObservable)
- 第一個(gè)參數(shù)傳遞的this就是LifecycleOwner 的實(shí)例,LiveData會(huì)根據(jù)Owner的聲明周期自動(dòng)作相應(yīng)的處理
- observe()將nameObservable作參數(shù)調(diào)用后,如果LiveData數(shù)據(jù)有值,onChange()立即調(diào)用獲取最新值
- 可以使用observeForever(Observer)方法注冊一個(gè)沒有關(guān)聯(lián)的生命周期所有者對象的觀察者,在這種情況下,觀察者被認(rèn)為總是活動(dòng)的,因此總是通知修改,可以刪除這些觀察員調(diào)用removeObserver(Observer) 方法
LiveData允許UI控制器觀察員訂閱更新
//設(shè)置點(diǎn)擊事件,修改LiveData中的數(shù)據(jù)
ld_btn.setOnClickListener{
mModel.mCurrent!!.value = "AAAAAA"
}
當(dāng)LiveData對象保存的數(shù)據(jù)發(fā)生變化時(shí),UI會(huì)自動(dòng)響應(yīng)更新
觀察者在從非活動(dòng)狀態(tài)變?yōu)榛顒?dòng)狀態(tài)時(shí)也會(huì)收到更新
運(yùn)行結(jié)果
點(diǎn)擊按鈕后改變LiveData的數(shù)據(jù),界面的TextView也隨之改變
擴(kuò)展LiveData
package andjun.com.mykt2019.java.livedata
import android.arch.lifecycle.LiveData
import android.content.Context
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import androidx.annotation.MainThread
/**
* author : AndJun
* time : 2019/3/12
* desc :
*/
class MyLocationLiveData(context: Context) : LiveData<Location>() {
private var locationManager: LocationManager? = null
init {
locationManager = context.getSystemService(
Context.LOCATION_SERVICE) as LocationManager
}
@MainThread
companion object {
private var sInstance: MyLocationLiveData? = null
fun getInstance(context: Context): MyLocationLiveData? {
if (sInstance == null) {
sInstance = MyLocationLiveData(context.applicationContext)
}
return sInstance
}
}
private var listener: LocationListener = object : LocationListener {
override fun onLocationChanged(location: Location?) {
}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
setValue(location)
}
override fun onProviderEnabled(provider: String?) {
}
override fun onProviderDisabled(provider: String?) {
}
}
override fun onActive() {
locationManager!!.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0.toLong(), 0.toFloat(), listener)
}
override fun onInactive() {
locationManager!!.removeUpdates(listener)
}
}
-
onActive() :當(dāng)LiveData對象具有活動(dòng)觀察者時(shí)調(diào)用該方法
-** onInactive()** :當(dāng)LiveData對象沒有任何活動(dòng)觀察者時(shí)調(diào)用該方法 - setValue(T) :方法更新LiveData實(shí)例的值,并通知任何活動(dòng)的觀察者有關(guān)更改的信息
-
postValue(T value)
: 其實(shí)是在非主線程中更新數(shù)據(jù),其實(shí)他傳遞的Runnable中也是調(diào)用了setValue()方法,其余的操作只是通過ArchTaskExecutor和DefaultTaskExecutor將操作切換到主線程
調(diào)用流程如下:
setValue(T value) --> dispatchingValue(null) --> considerNotify(iterator.next().getValue()) --> observer.mObserver.onChanged((T) mData)
所以 這里就去到了 Observer 觀察者的回調(diào)中,去更新具體操作
上面代碼使用單例提供LocationLiveData可以在Activity和Fragment之間實(shí)現(xiàn)共享,在onActive和onInactive中完成監(jiān)聽的注冊和取消,當(dāng)位置改變時(shí)回調(diào)Listener并調(diào)用setValue()設(shè)置LiveData的值,從而自動(dòng)更新觀察者中的數(shù)據(jù)
使用擴(kuò)展LIveData
擴(kuò)展的LiveData使用和正常使用一樣,observe()方法將Fragmrnt(它是一個(gè)實(shí)例LifecycleOwner)作為第一個(gè)參數(shù)傳遞,使觀察者綁定到Fragment的生命周期,如果Lifecycle對象未處于活動(dòng)狀態(tài),則即使值發(fā)生更改,也不會(huì)調(diào)用觀察者,在之后Lifecycle的對象被Destroy后,觀察者被自動(dòng)刪除
簡易源碼分析
- 加觀察者observe方法開始
observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
- 從參數(shù)中看到了LifecycleOwner,看到 從參數(shù)中看到了LifecycleOwner 應(yīng)該會(huì)想到這里的作用是處理生命周期改變(可以參考Lifecy 使用,源碼分析),在observe方法中執(zhí)行了以下邏輯
在observe中首先判斷了當(dāng)前Lifecycler的狀態(tài),當(dāng)Destroy時(shí)即觀察者不處于活躍狀態(tài),不用接收數(shù)據(jù)
創(chuàng)建LifecycleBoundObserver實(shí)例保存?zhèn)魅氲腖ifecycleOwner和Observer,并保存在mObservers
添加LifecycleOwner的觀察者,響應(yīng)生命周期的變化
- 在 observe 方法中的,ObserverWrapper 和 LifecycleBoundObserver
ObserverWrapper
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive(); // 當(dāng)Owner為活躍狀態(tài)時(shí)回調(diào)onActive()
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive(); // 當(dāng)Owner未活躍狀態(tài)時(shí)回調(diào)onInactive()
}
if (mActive) {
dispatchingValue(this);
}
}
LifecycleBoundObserver
// 實(shí)現(xiàn)GenericLifecycleObserver 當(dāng)生命周期改變時(shí)回調(diào)onStateChanged
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver); // DESTROYED時(shí)移除觀察者
return;
}
activeStateChanged(shouldBeActive());
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
ObserverWrapper 在Owner活躍狀態(tài)改變時(shí)回調(diào)onActive和onInactive方法,LifecycleBoundObserver主要利用Lifecycler的生命周期觀察者GenericLifecycleObserver,前面設(shè)置了owner.getLifecycle().addObserver(wrapper)后,當(dāng)生命周期改變時(shí)會(huì)回調(diào)onStateChange()方法,在生命周期為Destroy時(shí)移除Observer
小結(jié)
LiveData 整個(gè)過程就是兩部分
- 一是使用LifeCycleOwner感知聲明周期的變化
- 第二就是儲(chǔ)存并遍歷Observer,在數(shù)據(jù)改變時(shí)回調(diào)所有的觀察者