Jetpack(一)Lifecycle和LiveData

源碼分析:JetPacks之Lifecycles原理
應用:JetPacks之數據傳遞工具
聯系:JetPack之 LifeCycle LiveData

Lifecycle

  • Lifecycle可以有效的避免內存泄漏和解決android生命周期的常見難題
  • Lifecycle 是一個表示android生命周期及狀態的對象
  • LivecycleOwner 用于連接有生命周期的對象,如activity,fragment
  • LivecycleObserver 用于觀察查LifecycleOwner

基本使用

Lifecycle框架使用觀察者模式實現觀察者監聽被觀察者的生命周期的變化

定義被觀察者>>

通過實現LifecycleOwner接口

ComponentActivity.png

如上圖:我們使用activity不需要再自己寫實現接口的代碼

定義觀察者>>

通過實現LifecycleObserver接口

BasePresenter.png

通過注解在觀察者類中定義需要監聽的生命周期

注:以下方法都會在被觀察者生命周期變化時調用
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreateX(LifecycleOwner owner) {

    }


    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStartX(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onStop(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    void onResume(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    void onPause(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestory(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onAny(LifecycleOwner owner) {
    }

完成訂閱關系>>

在activity中使用

被觀察者.addObserver(觀察者)
getLifecycle().addObserver(presenter);

環境配置>>

自己引入
dependencies {
  implementation "androidx.lifecycle:lifecycle-runtime:2.0.0"
  implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
  implementation "androidx.lifecycle:lifecycle-common-java8:2.0.0"
  annotationProcessor  "androidx.lifecycle:lifecycle-compiler:2.0.0"
}

核心原理

LifecycleRegister#addObserver

看一下LifecycleRegister 類中的addObserver方法這里你會發現生成了一個ObserverWithState,然后放入FastSafeIterableMap里,這個類是一個自定義列表,用于保存觀察者并可在遍歷期間處理刪除/添加。

  1. AppCompatActivity

AppCompatActivity 實現了LifecycleOwner接口,同時持有實現了Lifecycle的LifecycleRegistry對象,這個對象就可以將其理解為觀察者模式中的Observable,LifecycleRegistr聚合多個LifecycleObserver,生命周期改變時通知LifecycleObserver進行相應的方法調用。

  1. ReportFragment Commponent#ReportFragment.injectIfNeededIn

AppCompatActivity 繼承的extends androidx.core.app.ComponentActivity中的onCretae方法ReportFragment.injectIfNeededIn(this);
就是在當前的Activity里添加一個ReportFragment。

  1. ReportFragment#dispatch()

再看ReportFragment的生命周期函數
你會發現都調用了dispatch()方法,

  1. LifecycleRegistry#handleLifecycleEvent

而dispatch()方法則會判斷Activity是否實現了LifecycleOwner接口,如果實現了該接口就調用LifecycleRegister的handleLifecycleEvent()
這樣生命周期的狀態就會借由LifecycleRegistry通知給各個LifecycleObserver從而調用其中對應Lifecycle.Event的方法。這種通過Fragment來感知Activity生命周期的方法其實在Glide的中也是有體現的。

  1. handleLifecycleEvent--->getStateAfter

回到handleLifecycleEvent方法中
State next = getStateAfter(event);
事件發生的時候,先得到當前activity應該出現的下一個狀態

  1. 狀態機流轉

moveToState(next);
mState = next;更新現在的狀態
sync();
backwardPass(lifecycleOwner);逆推
forwardPass(lifecycleOwner);

state.png
  1. forwardPass(lifecycleOwner)

forwardPass(lifecycleOwner)方法中的細節
ObserverWithState observer = entry.getValue();
找到ObserverWithState 類
調用mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
生成觀察者適配器

  1. onStateChanged

接下來就是調用onStateChanged(),來通知 實現了 LifecycleObserver的類,生命周期發生了變化

  1. ReflectiveGenericLifecycleObserver

查看實現類
ReflectiveGenericLifecycleObserver。onStateChanged()

ReflectiveGenericLifecycleObserver。的構造方法中就把presenter中的方法和注解保存了下來
再通過onStateChanged()進行生命周期的方法的調用

源碼分析 JetPacks之Lifecycles原理

應用 JetPacks之數據傳遞工具

Demo JetPack之 LifeCycle LiveData

LiveData

LiveData是一種具有生命周期感知能力的可觀察數據持有類
LiveData可以保證屏幕上的顯示內容和數據一直保持同步
特點:
1.LiveData了解UI界面的狀態,如果activity不在屏幕上顯示,livedata不會觸發沒必要的界面更新,如果activity已經被銷毀,會自動清空與observer的連接,意外的調用就不會發生
2.LiveData是一個LifecycleOwner,他可以直接感知activity或fragment的生命周期

基本使用

定義LifeData >>

項目中livedata一般都存放在ViewModel中,以保證app配置變更時,數據不會丟失

舉個例子:

public class NameViewModel extends ViewModel {
    public int i = 0;
    private MutableLiveData<String> currentName;
    public MutableLiveData<String> getCurrentName(){
        if(currentName==null){
            currentName=new MutableLiveData<>();
        }
        return currentName;
    }
}

使用流程 >>

定義觀察者用以觀察livedata中的數據變化

//需要一個觀察者來觀察數據
        Observer observer=new Observer<String>(){
            @Override
            public void onChanged(String s) {
                nameTextView.setText(s);
            }
        };

livedata訂閱observer

        //獲取到viewmodel
        model= ViewModelProviders.of(this).get(NameViewModel.class);
        //取出livedata完成訂閱
        model.getCurrentName().observe(this,observer);

livedata發送消息通知observer更新數據

model.getCurrentName().setValue(anotherName);
以上代碼會回調observer中的onChanged方法

使用注意:

setValue只能在主線程運行

postValue只能在子線程中運行

核心原理

1.observe做為入口>>

使用LifecycleBoundObserver把觀察者和被觀察者包裝在一起
綁定wrapper作為觀察者

綁定完成后,使用setValue與postValue通知觀察者

  1. setValue中 >>

-------dispatchingValue(null)
if (initiator != null)
參數傳null和不傳null的區別就是如果傳null將會通知所有的觀察者,反之僅僅通知傳入的觀察者。
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
通知所有的觀察者通過遍歷 mObservers ,將所有的 ObserverWrapper 拿到,實際上就是我們上面提到的 LifecycleBoundObserver,通知觀察者調用considerNotify()方法,這個方法就是通知的具體實現了。

-------considerNotify()

先用2個if判斷出被觀察者對應的activity狀態是否為顯示
發送通知 onChanged()被調用

  1. postValue中 >>

切換線程到主線程中去執行setValue

LiveDataEventBus

通過一個集合統一管理所有的LiveData
設計中的BUG:
原來的執行順序new LiveData-->綁定observer-->setValue執行onChanged
而我們的BUS在用時可能出現 new LiveData-->setValue執行onChanged-->綁定observer
處理方案,讓第一次setValue不起效即可

參考Github

LiveDataBus

package top.zcwfeng.jetpack.utils;

import androidx.lifecycle.MutableLiveData;

import java.util.HashMap;
import java.util.Map;

public class LiveDataBus {
    //存放訂閱者
    private Map<String, MutableLiveData<Object>> bus;
    private static LiveDataBus liveDataBus = new LiveDataBus();

    private LiveDataBus() {
        bus = new HashMap();
    }
    public static LiveDataBus getInstance() {
        return liveDataBus;
    }
    //注冊訂閱者
    public synchronized <T> MutableLiveData<T> with(String key, Class<T> type) {
        if(!bus.containsKey(key)){
            bus.put(key,new MutableLiveData<Object>());
        }
        return (MutableLiveData<T>)bus.get(key);
    }
}

LiveDataXBus 解除 LiveDataBus 粘性問題,某些場景需要

/**
 * 解除 LiveDataBus 粘性問題,某些場景需要
 */
public class LiveDataBusX {
    //存放訂閱者
    private Map<String, BusMutableLiveData<Object>> bus;

    private static LiveDataBusX liveDataBus = new LiveDataBusX();

    private LiveDataBusX() {
        bus = new HashMap<>();
    }

    public static LiveDataBusX getInstance() {
        return liveDataBus;
    }

    //注冊訂閱者,(存入map) Hook前用MutableLiveData
    public synchronized <T> BusMutableLiveData<T> with(String key, Class<T> type){
        if(!bus.containsKey(key)){
            bus.put(key,new BusMutableLiveData<Object>());
        }
        return (BusMutableLiveData<T>) bus.get(key);
    }

    public static class BusMutableLiveData<T> extends MutableLiveData<T> {
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            super.observe(owner, observer);
            hook(observer);
        }
        //在這里去改變onChange的流程
        private void hook(Observer<? super T> observer) {
            try {
                //1.得到mLastVersion
                //獲取到LiveData的類中的mObservers對象
                Class<LiveData> liveDataClass = LiveData.class;
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                mObserversField.setAccessible(true);
                //獲取到這個成員變量的對象
                Object mObserversObject = mObserversField.get(this);
                //得到map對應的class對象
                Class<?> mObserversClass = mObserversObject.getClass();
                //獲取到mObservers對象的get方法
                Method get = mObserversClass.getDeclaredMethod("get", Object.class);
                get.setAccessible(true);
                //執行get方法
                Object invokeEntry=get.invoke(mObserversObject,observer);
                //定義一個空的對象
                Object observerWraper=null;
                if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
                    observerWraper=((Map.Entry)invokeEntry).getValue();
                }
                if(observerWraper==null){
                    throw new NullPointerException("observerWraper is null");
                }
                //得到ObserverWrapper的類對象  編譯擦除問題會引起多態沖突所以用getSuperclass
                Class<?> superclass = observerWraper.getClass().getSuperclass();
                Field mLastVersion = superclass.getDeclaredField("mLastVersion");
                mLastVersion.setAccessible(true);
                //2.得到mVersion
                Field mVersion = liveDataClass.getDeclaredField("mVersion");
                mVersion.setAccessible(true);
                //3.把mVersion的數據填入到mLastVersion中
                Object mVersionValue=mVersion.get(this);
                mLastVersion.set(observerWraper,mVersionValue);


            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}

目錄:

Jetpack(一)Lifecycle和LiveData
JetPacks之Lifecycles原理
JetPack之 LifeCycle LiveData

Jetpack(二)之DataBinding

Jetpack(三) 之 Room 與 ViewModel
Jetpack 之 ViewModel 原理

Jetpack (四) 之 Navigation
Jetpack Navigation 原理淺析

JetPack (五)之 Paging 分頁庫

Jetpack(六) 之 WorkManager
Jetpack WorkManager 原理

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在《也談Android應用架構》中我們對MVC、MVP、MVVM進行了詳盡的分析,但還有一個問題懸而未決,那就是生...
    大大紙飛機閱讀 975評論 0 6
  • 久違的晴天,家長會。 家長大會開好到教室時,離放學已經沒多少時間了。班主任說已經安排了三個家長分享經驗。 放學鈴聲...
    飄雪兒5閱讀 7,556評論 16 22
  • 今天感恩節哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開了第一次的黨會,身份的轉變要...
    迷月閃星情閱讀 10,607評論 0 11
  • 可愛進取,孤獨成精。努力飛翔,天堂翱翔。戰爭美好,孤獨進取。膽大飛翔,成就輝煌。努力進取,遙望,和諧家園。可愛游走...
    趙原野閱讀 2,767評論 1 1
  • 在妖界我有個名頭叫胡百曉,無論是何事,只要找到胡百曉即可有解決的辦法。因為是只狐貍大家以訛傳訛叫我“傾城百曉”,...
    貓九0110閱讀 3,331評論 7 3