前言
最近在學習 Google 推出的框架Jetpack析显,雖然目前網上的資料已經很多了哀托,但為了加深印象和邊動手練習跟著學習,所以站在了下面的巨人的肩膀上移斩,并根據當前最新的API 和編寫實際Demo,記錄下一些學習筆記,大部分是參考巨人們的咬腋,整理和休整羹膳,加入自己理解和更新吧,學習領略了Android Jetpack組件的一點魅力
目前學習筆記系列為:
- Android Jetpack 之 Lifecycles ---入門使用
- Android Jetpack 之 LiveData---入門使用
- Android Jetpack 之 Room ---入門使用
- Android Jetpack 之 WorkManger---入門使用
- ....待續(xù)
日常鳴謝巨人
正題
LiveData 簡介
- LiveData是一個具有生命周期感知特性的可觀察的數據保持類根竿,使用LiveData保存數據時陵像,在每次訂閱或數據更新時會自動回調設置的觀察者從而更新數據,真正的實現了數據驅動的效果
- LiveData的創(chuàng)建基本會在ViewModel中犀填,從而使數據在界面銷毀時繼續(xù)保持
- LiveData 認為觀察者的生命周期處于STARTED狀態(tài)或RESUMED狀態(tài)下蠢壹,表示觀察者處于活動狀態(tài),LiveData只通知活躍的觀察者更新數據
- 注冊一個實現該LifecycleOwner 接口的對象配對的觀察者九巡,當相應Lifecycle對象的狀態(tài)改變?yōu)镈ESTROYED時需移除觀察者
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)建一個LiveData實例來保存某種類型的數據
class TestViewModel : ViewModel() {
var mCurrent: MutableLiveData<String>? = null
get() {
if (field == null) {
field = MutableLiveData()
}
return field
}
}
確保存儲LiveData對象是在ViewModel中而不 是Activity 或 Fragment 中
創(chuàng)建一個定義onChanged()方法的Observer對象,在數據變化時回調
// 創(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)
- 第一個參數傳遞的this就是LifecycleOwner 的實例,LiveData會根據Owner的聲明周期自動作相應的處理
- observe()將nameObservable作參數調用后偿洁,如果LiveData數據有值撒汉,onChange()立即調用獲取最新值
- 可以使用observeForever(Observer)方法注冊一個沒有關聯的生命周期所有者對象的觀察者,在這種情況下涕滋,觀察者被認為總是活動的睬辐,因此總是通知修改,可以刪除這些觀察員調用removeObserver(Observer) 方法
LiveData允許UI控制器觀察員訂閱更新
//設置點擊事件宾肺,修改LiveData中的數據
ld_btn.setOnClickListener{
mModel.mCurrent!!.value = "AAAAAA"
}
當LiveData對象保存的數據發(fā)生變化時溯饵,UI會自動響應更新
觀察者在從非活動狀態(tài)變?yōu)榛顒訝顟B(tài)時也會收到更新
運行結果
點擊按鈕后改變LiveData的數據,界面的TextView也隨之改變
擴展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() :當LiveData對象具有活動觀察者時調用該方法
-** onInactive()** :當LiveData對象沒有任何活動觀察者時調用該方法 - setValue(T) :方法更新LiveData實例的值锨用,并通知任何活動的觀察者有關更改的信息
-
postValue(T value)
: 其實是在非主線程中更新數據丰刊,其實他傳遞的Runnable中也是調用了setValue()方法,其余的操作只是通過ArchTaskExecutor和DefaultTaskExecutor將操作切換到主線程
調用流程如下:
setValue(T value) --> dispatchingValue(null) --> considerNotify(iterator.next().getValue()) --> observer.mObserver.onChanged((T) mData)
所以 這里就去到了 Observer 觀察者的回調中增拥,去更新具體操作
上面代碼使用單例提供LocationLiveData可以在Activity和Fragment之間實現共享啄巧,在onActive和onInactive中完成監(jiān)聽的注冊和取消寻歧,當位置改變時回調Listener并調用setValue()設置LiveData的值,從而自動更新觀察者中的數據
使用擴展LIveData
擴展的LiveData使用和正常使用一樣秩仆,observe()方法將Fragmrnt(它是一個實例LifecycleOwner)作為第一個參數傳遞码泛,使觀察者綁定到Fragment的生命周期,如果Lifecycle對象未處于活動狀態(tài)澄耍,則即使值發(fā)生更改弟晚,也不會調用觀察者,在之后Lifecycle的對象被Destroy后逾苫,觀察者被自動刪除
簡易源碼分析
- 加觀察者observe方法開始
observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
- 從參數中看到了LifecycleOwner卿城,看到 從參數中看到了LifecycleOwner 應該會想到這里的作用是處理生命周期改變(可以參考Lifecy 使用,源碼分析)铅搓,在observe方法中執(zhí)行了以下邏輯
在observe中首先判斷了當前Lifecycler的狀態(tài)瑟押,當Destroy時即觀察者不處于活躍狀態(tài),不用接收數據
創(chuàng)建LifecycleBoundObserver實例保存?zhèn)魅氲腖ifecycleOwner和Observer星掰,并保存在mObservers
添加LifecycleOwner的觀察者多望,響應生命周期的變化
- 在 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(); // 當Owner為活躍狀態(tài)時回調onActive()
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive(); // 當Owner未活躍狀態(tài)時回調onInactive()
}
if (mActive) {
dispatchingValue(this);
}
}
LifecycleBoundObserver
// 實現GenericLifecycleObserver 當生命周期改變時回調onStateChanged
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver); // DESTROYED時移除觀察者
return;
}
activeStateChanged(shouldBeActive());
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
ObserverWrapper 在Owner活躍狀態(tài)改變時回調onActive和onInactive方法氢烘,LifecycleBoundObserver主要利用Lifecycler的生命周期觀察者GenericLifecycleObserver怀偷,前面設置了owner.getLifecycle().addObserver(wrapper)后,當生命周期改變時會回調onStateChange()方法播玖,在生命周期為Destroy時移除Observer
小結
LiveData 整個過程就是兩部分
- 一是使用LifeCycleOwner感知聲明周期的變化
- 第二就是儲存并遍歷Observer椎工,在數據改變時回調所有的觀察者