Andorid 狀態管理(一)Lifecycle淺析

原理概述

Lifecycle主要用於Activity、Fragment這一類具備狀態的組件的狀態監聽,最主要的一個做用就是將原先Activity、Fragment中的大量的生命週期相關的回調函數移出View層文件,從設計角度上來講,使得MVVM中的View層文件的結構更加清晰、簡單,簡化了View層的任務,使得代碼更清晰、易於維護。html

Lifecycle實現監聽的原理主要有兩種方式,在API29如下的版本主要採用的是方法一,而在API29+的版本採用的是方法二。java

  1. 和Glide插件同樣的,採用一個專門用於報告狀態的Fragment,當這個特殊的空白Fragment被插入到宿主Activity時,就能夠獲取到宿主的生命週期狀態改變。
  2. 實現Application.ActivityLifecycleCallbacks,監聽相關的生命週期的改變。

大概的使用步驟以下:android

  • 聲明本身的監聽組件:MyUtil實現LifecycleObserver接口
  • 採用註解聲明生命週期回調函數:
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    private void fun1(){
        //on_create時須要作的事情
    }
複製代碼
  • 在MainActivity.java中調用:
getLifecycle().addObserver(new MyUtil());
複製代碼

顯然,在這個模型中,lifecycle自己只是一個事件的源頭,而咱們本身實現的監聽者MyUtil則是觀察者,咱們像lifecycle註冊咱們的工具,一旦lifecycle收到了生命週期的變化通知,那麼就通知一系列的觀察者進行更新:git

未命名文件.png

Lifecycle自己更像是一個代理,咱們的工具類不須要本身去作監聽這一件事情了,因此這實際上能夠看作是兩個觀察者模式的合成,而中間的lifecycle是一個系統爲咱們提供的接口,用於得到回調。咱們只須要註冊咱們的Observer便可。這樣一來,分析lifecycle的過程明顯被拆成了兩個子問題:github

問題1. MyUtil(LifecycleObserver)是如何監聽lifecycle的?web

問題2. lifecycle是如何監聽宿主(LifecycleOwner)生命週期變化的?編程

構成

Lifecycle的構成對象:markdown

  • Lifecycle:即生命週期,某個組件(Activity、Fragment)可能會具備本身的Lifecycle。
  • LifecycleOwner:Lifecycle的持有者,某個組件(Activity、Fragment)。
  • LifecycleObserver:即觀察者,咱們須要對某個組件的生命週期進行觀察,那麼就必須實現LifecycleObserver,經過lifecycle的addObserver方法對LifecycleObserver進行註冊監聽,這樣一來對應的LifecycleObserver的類就可以獲得生命週期的相關回調了。
  • Event:即生命週期回調的方法,例如ON_CREATE、ON_START等等。
  • State:當某個Event發生後,會致使State的轉變,例如ON_CREATE事件發生時,State將會從INITIALIZED走向CREATED,以下【模型】中的狀態轉移關係圖。
    • INITIALIZED:剛剛被初始化。
    • CREATED:ON_CREATE以後、ON_STOP以後。
    • STARTED:ON_START以後、ON_PAUSE以後。
    • RESUMED:ON_RESUME以後、ON_PAUSE以前
    • ON_DESTORYED:ON_DESTROY以後,還未被建立或者已經銷燬。

模型

Lifecycle run model.png

//對應的狀態轉移函數
@NonNull
public State getTargetState() {
  	//枚舉類,this標識的是某種事件,例如ON_CREATE、ON_STOP等等。
    switch (this) {
        //對於ON_CREATE和ON_STOP事件,都對應CREATED狀態。(圖上兩者都指向CREATED)
        case ON_CREATE:
        case ON_STOP:
            return State.CREATED;
        case ON_START:
        case ON_PAUSE:
            return State.STARTED;
        case ON_RESUME:
            return State.RESUMED;
        case ON_DESTROY:
            return State.DESTROYED;
        case ON_ANY:
            break;
    }
    throw new IllegalArgumentException(this + " has no target state");
}
複製代碼

源碼

1. addObserver(observer)

LifecycleOwner做爲事件的源頭,Fragment、Activity都是LifecycleOwner。換句話說就是這二者會產生一些列生命週期相關的事件。網絡

public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner 複製代碼

LifecycleOwner提供了惟一一個方法,而且,在ComponentActivity類中,使用的是Lifecycle的一個實現類:mLifecycleRegistryapp

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}

private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
複製代碼
//LifecycleRegistry.java
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    enforceMainThreadIfNeeded("addObserver");//主線程斷言
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;//若是mState是已經銷燬的則就標記爲已經銷燬;若是是其餘的(全部有效的),就標記爲已初始化過的。
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);//傳入自定義的觀察者(非被觀察者)和狀態。
    ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);//嘗試放入被觀察者維護的觀察者對象集合中(若是不存在的話,防止屢次註冊)。若是存在,返回既有值的value;若是不存在put,並返回null。
  	//若是以前存在一個相同的observer,那麼直接return;
    if (previous != null) {
        return;
    }
  	//取得lifecycleOwner對象,一般是Activity或者是Fragment,注意,此處的LifecycleOwner是被WeakReference<LivecycleOwner>引用住的。是在LifecycleRegistry的構造函數中,被注入了值。
   	//private final WeakReference<LifecycleOwner> mLifecycleOwner;
  
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
  
  	//若是爲空,說明對象已經被回收了,return掉。
    if (lifecycleOwner == null) {
        // it is null we should be destroyed. Fallback quickly
        return;
    }

    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter++;
		//正在註冊的觀察者數量+1
  	
  	//ENUM Class之間的比較,兩者相等會返回0。這個循環做用就是追加以前的生命週期事件派發(粘性)
    while ((statefulObserver.mState.compareTo(targetState) < 0
            && mObserverMap.contains(observer))) {
      	//該行代碼的內部實現是:mParentStates.add(state);其中的mParentStates是一個ArrayList,用於存儲一些「舊」的消息。例如咱們在running(create、start、resume都走完了)狀態經過點擊按鈕註冊一個監聽,此時的pushParentState中的參數:statefulObserver.mState就是「INITIALIZED」。
        pushParentState(statefulObserver.mState);
      	//接着上面的狀況,傳入的參數是:INITIALIZED,從upFrom中取出的Event是「ON_CREATE」,可是此時onCreate狀態實際上早已走完了。
        final Event event = Event.upFrom(statefulObserver.mState);
        if (event == null) {
            throw new IllegalStateException("no event up from " + statefulObserver.mState);
        }
      	//注意,咱們在實例中的ON_CREATE等等回調都是在這步裏面執行的【圖1】,主要是更新狀態,和派發事件,走完這代碼,statefulObserver.mState就變成了CREATED
        statefulObserver.dispatchEvent(lifecycleOwner, event);
      	
      	//和pushParentState對應,此時刪除後parentState長度爲0。
        popParentState();
      
      	
        targetState = calculateTargetState(observer);
      	//此時statefulObserver.mState爲CREATED,而targetState的值被更新爲:RESUME。
    }
  	
    if (!isReentrance) {
        // we do sync only on the top level.
        sync();
    }
    mAddingObserverCounter--;
}
複製代碼

接下來的第二輪代碼的,其實和第一輪相似,就是從Event從ON_CREATE變成了ON_START,而後派發了ON_START事件。ON_RESUME同理。大概的流程是,添加Observer的時候。以statefulObserver爲主,不論Activity是什麼狀態,進入時initialState都是INITIALIZED狀態,而後利用Event.upFrom函數,根據狀態(State,例如CREATED),取出事件(Event,例如ON_CREATE),而後, statefulObserver.dispatchEvent(lifecycleOwner, event);更新了statefulObserver的狀態,依次類推。

lifecycle圖1.png

以上代碼的幾個比較關鍵的展開:

private State calculateTargetState(LifecycleObserver observer) {
  	
  	//mObserverMap即上面addObserver主幹代碼中的第七行:
  	//ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
  	//此處是對該Map惟一的加入調用。
	
  	//取出臨近的ObserverWithState,FastSafeIterableMap,註釋中說是:Poor's man LinkedHashMap
  	//LifecycleObserver在androidx.core.app.ComponentActivity中能夠看到,ComponentActivity實現了該接口。
  	//因此,該Map是一個Activity對應ObserverWithState(一個State、一個LifecycleEventObserver)的結構:
  	
    Map.Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);

  	//若是不爲空,那麼就設置siblingState爲previous中存儲對象的mState else null
    State siblingState = previous != null ? previous.getValue().mState : null;
  	//若是有parentState,那麼獲取其中的最後一個的State else null
    State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
            : null;
  	//取mState、siblingState和parentState中最小值。
    return min(min(mState, siblingState), parentState);
}


//statefulObserver.dispatchEvent(lifecycleOwner, event); 
void dispatchEvent(LifecycleOwner owner, Event event) //根據event(ENUM)獲取其狀態,這個和上面的狀態圖是同樣的。 State newState = event.getTargetState();
	 //取最小狀態
   mState = min(mState, newState);
   //更新狀態,響應回調
   mLifecycleObserver.onStateChanged(owner, event);
	 //設置新狀態
   mState = newState;
}

複製代碼

image-20210427210806747.png

2. sync()

private void sync() {
  	//即Activity、Fragment這類生命週期持有者。
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
  	//判斷是否已經被回收
    if (lifecycleOwner == null) {
        throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                + "garbage collected. It is too late to change lifecycle state.");
    }
  	//若是mObserverMap中的元素尚未徹底同步就進行循環,進行全部保存着的觀察者的狀態同步。
    while (!isSynced()) {
      	//標記是否有新的事件出現,當moveToState被調用時,知足條件(mHandlingEvent || mAddingObserverCounter != 0)時,該屬性會被置爲true。
      	//這兩個條件是:1是否正在處理事件,2是是否正在處理新加入的觀察者。
        mNewEventOccurred = false;
        //利用mState和mObserverMap中最老的元素狀態相比較,若是更小(最小的是DESTROY,INITIALIZED,一直到RESUMED),那麼久從最先被加入的元素,順着這個LinkedHashMap進行後向的更新。例如CREATED < RESUMED
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
          	//後向傳播
            backwardPass(lifecycleOwner);
        }
        Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
      	//若是沒有新的事件出現(期間沒有moveToState被觸發),最新的觀察者不爲空,而且有當前組件的狀態更先於最新組件的狀態。
      	//例如mState = RESUMED和newest.mState = CREATED,那麼就觸發前向傳播。
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
          	//前向傳播
            forwardPass(lifecycleOwner);
        }
      	//在這個循環中,直到全部Observer狀態所有同步爲止。
    }
    mNewEventOccurred = false;
}

private boolean isSynced() {
  	if (mObserverMap.size() == 0) {
    	return true;
  	}
  	State eldestObserverState = mObserverMap.eldest().getValue().mState;
  	State newestObserverState = mObserverMap.newest().getValue().mState;
  	//判斷最晚加入的 是否等於 最先加入的 是否等於 當前的狀態。
  	return eldestObserverState == newestObserverState && mState == newestObserverState;
}
複製代碼
//forwardPass同理;
private void backwardPass(LifecycleOwner lifecycleOwner) {
  	//迭代器
    Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
            mObserverMap.descendingIterator();
  	//在forwardPass中:
    //Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
    // mObserverMap.iteratorWithAdditions();
  	//在沒有新的事件(moveToState觸發)的狀況下進行迭代。
    while (descendingIterator.hasNext() && !mNewEventOccurred) {
        Map.Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
        ObserverWithState observer = entry.getValue();
        while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
          	//和addObserver中類似的邏輯,同步時主動去回調其餘滯後的監聽者的狀態。
            Event event = Event.downFrom(observer.mState);
            if (event == null) {
                throw new IllegalStateException("no event down from " + observer.mState);
            }
            pushParentState(event.getTargetState());
            observer.dispatchEvent(lifecycleOwner, event);
            popParentState();
        }
    }
}
複製代碼

3. setCurrentState、moveToState

這一類的方法用於外部調用,用於lifecycle的狀態轉移。例如咱們能夠顯式地在一個Activity的全部生命週期中,調用setCurrentState方法來標記(通知)lifecycle狀態。標記完成後,將觸發sync進行全部觀察者狀態的同步。

@MainThread
    public void setCurrentState(@NonNull State state) {
        enforceMainThreadIfNeeded("setCurrentState");//斷言主線程
        moveToState(state);
    }

    /** * Sets the current state and notifies the observers. * <p> * Note that if the {@code currentState} is the same state as the last call to this method, * calling this method has no effect.(若是在相同的State下調用此方法無效。) * * @param event The event that was received */
    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        enforceMainThreadIfNeeded("handleLifecycleEvent");//斷言主線程
        moveToState(event.getTargetState());
    }

    private void moveToState(State next) {
      	//相同狀態下調用無效。
        if (mState == next) {
            return;
        }
        mState = next;
      	//若是正在處理事件,或者含有某個剛剛加入的Observer(數量不爲0),那麼久標記當前有新的事件出現了。
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;//標記正在處理事件,有點像鎖
        sync();//同步(先後向傳播)
        mHandlingEvent = false;//結束
    }


複製代碼

監聽

從moveToState提及,它有三個調用。

@Deprecated
@MainThread
public void markState(@NonNull State state) {
    enforceMainThreadIfNeeded("markState");
    setCurrentState(state);
}

@MainThread
public void setCurrentState(@NonNull State state) {
    enforceMainThreadIfNeeded("setCurrentState");
    moveToState(state);
}

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    enforceMainThreadIfNeeded("handleLifecycleEvent");
    moveToState(event.getTargetState());
}
複製代碼

markState已經被標記爲@Deprecated,可是咱們能夠找到它的一個調用:package androidx.core.app下的ComponentActivity中的onSaveInstanceState仍然保持着這個方法的調用。

package androidx.core.app;

@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    mLifecycleRegistry.markState(Lifecycle.State.CREATED);//
    super.onSaveInstanceState(outState);
}
複製代碼

setCurrentState則在package androidx.activity;中的ComponentActivity被引用:

package androidx.activity;

@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    Lifecycle lifecycle = getLifecycle();
    if (lifecycle instanceof LifecycleRegistry) {
        ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);//
    }
    super.onSaveInstanceState(outState);
    mSavedStateRegistryController.performSave(outState);
}
複製代碼

至於handleLifecycleEvent:

QQ20210428-173315@2x.png

很明顯在AppcompatActivity中,handleLifecycleEventlifecyle的關係比較密切。

例如,在onCreate方法中,有:

protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);

        if (savedInstanceState != null) {
           //若是是重建的Activity進行的操做,如下省略
           ......
        }

        if (mPendingFragmentActivityResults == null) {
            mPendingFragmentActivityResults = new SparseArrayCompat<>();
            mNextCandidateRequestIndex = 0;
        }

        super.onCreate(savedInstanceState);

        mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);//派發事件
        mFragments.dispatchCreate();
    }

複製代碼

每當咱們的Activity父類的FragmentActivity的方法:onCreate被回調時,必然會觸發handleLifecycleEvent()的執行,這樣一來很是簡單地就實現了監聽。

可是,在androidx.activity.ComponentActivity;中,有一段很是特殊的代碼:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedStateRegistryController.performRestore(savedInstanceState);
    ReportFragment.injectIfNeededIn(this);//
    if (mContentLayoutId != 0) {
        setContentView(mContentLayoutId);
    }
}
複製代碼
public static void injectIfNeededIn(Activity activity) {
    if (Build.VERSION.SDK_INT >= 29) {
        // On API 29+(Android 10.0 +), 咱們能夠直接註冊正確的lifecycle監聽,內部將會直接實現監聽:在Activity類中的mActivityLifecycleCallbacks中,加入一個Callback:mActivityLifecycleCallbacks.add(callback);
        activity.registerActivityLifecycleCallbacks(
                new LifecycleCallbacks());
    }
		
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
      	//注意這裏,咱們向當前的Activity中新加入了一個new ReportFragment()。
        manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
        manager.executePendingTransactions();
    }
}
複製代碼

任取一個Fragment的生命週期函數做爲觀察,進入dispatch()方法。

@Override
public void onStart() {
    super.onStart();
    dispatchStart(mProcessListener);
    dispatch(Lifecycle.Event.ON_START);
}

@Override
public void onResume() {
    super.onResume();
    dispatchResume(mProcessListener);
    dispatch(Lifecycle.Event.ON_RESUME);
}

@Override
public void onPause() {
    super.onPause();
    dispatch(Lifecycle.Event.ON_PAUSE);
}
複製代碼

在dispatch方法中,發現將activity當作LifecycleOwner獲取了其Lifecycle進行事件的處理。

@SuppressWarnings("deprecation")
static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
    if (activity instanceof LifecycleRegistryOwner) {
        ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);//
        return;
    }

    if (activity instanceof LifecycleOwner) {
        Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);//
        }
    }
}
複製代碼

其中,LifecycleRegistryOwner是LifecycleOwner接口的子類,能夠看到返回值不一樣。顯然,當Activity生命週期發生變更時,Fragment的生命週期也會相應地發生變更,由ReportFragment的生命週期函數中進行handleLifecycleEvent就很是巧妙地實現了監聽這一功能。這一點和Glide的實現(採用一個空白的RequestManagerFragment)很是類似。

ReportFramgnet.png

可是,在API29+,程序會走這樣一段代碼:

public static void injectIfNeededIn(Activity activity) {
    if (Build.VERSION.SDK_INT >= 29) {
        // On API 29+, we can register for the correct Lifecycle callbacks directly
        LifecycleCallbacks.registerIn(activity);
    }
    //……
}

static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {

  	//有作省略
    static void registerIn(Activity activity) {
        activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
    }
    @Override
    public void onActivityPostCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
        dispatch(activity, Lifecycle.Event.ON_CREATE);
    }
    @Override
    public void onActivityPostStarted(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_START);
    }
    @Override
    public void onActivityPostResumed(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_RESUME);
    }
    @Override
    public void onActivityPrePaused(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_PAUSE);
    }
    @Override
    public void onActivityPreStopped(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_STOP);
    }
    @Override
    public void onActivityPreDestroyed(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_DESTROY);
    }
}
複製代碼

同時,Api29+的機型,也會走到:插入一個ReportFragment。理論上,經過Application.ActivityLifecycleCallbacks 回調就已經可以註冊到監聽了,至於爲何這麼設計並不清楚。可是到派發事件時的dispatch方法:

private void dispatch(@NonNull Lifecycle.Event event) {
    if (Build.VERSION.SDK_INT < 29) {
        dispatch(getActivity(), event);//TAG
    }
}
複製代碼

它限制了經過Fragment生命週期回調產生的監聽只在Api<29纔會進行派發,因此不會產生兩次派發。而標記的TAG處的dispatch是一個靜態方法,注意,API29+的dispatch直接就是調用的這個靜態方法。

static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
    if (activity instanceof LifecycleRegistryOwner) {
        ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
        return;
    }

    if (activity instanceof LifecycleOwner) {
        Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
        }
    }
}

//API29中的調用,走的是上面的靜態方法。
@Override
public void onActivityPostStarted(@NonNull Activity activity) {    
	  dispatch(activity, Lifecycle.Event.ON_START);
}
複製代碼

不管是API29如下經過Fragment監聽,仍是API29以上,經過Application.ActivityLifecycleCallbacks進行監聽,走的都是lifecycle.handleLifecycleEvent()方法。這也是爲何在上文中提handleLifecycleEvent有大量調用的調用:

QQ20210428-173315@2x.png

其餘

1. Application.ActivityLifecycleCallbacks

該接口含有大量的回調函數,和平常開發中的那三對回調函數不一樣,這裏的劃分更加細緻,有三組,而且每組又區分pre和post,外加一個onActivitySaveInstanceState,每當Activity發生生命週期轉變時,該回調函數都會被回調到,而且參數是發生變化的Activity。咱們能夠自定義一個類實現該接口,而後this.registerActivityLifecycleCallbacks(callbacks);註冊一下便可。該類還能夠實現更靈活的Activity 實例數量管控。大部分的事件都是在POST部分中處理的,而不是Pre。

@Override
public void onActivityResumed(@NonNull Activity activity) {
}
@Override
public void onActivityPostResumed(@NonNull Activity activity) {
    dispatch(activity, Lifecycle.Event.ON_RESUME);//向監聽者(MyUtils類等等)派發事件
}
複製代碼

總結

從監聽開始,在API29如下的版本中,會向Activity中加入一個ReportFragment,該Fragment的生命週期發生變化時,將會進行派發時間,更新lifecycle的生命週期,再由Lifecycle統一通知LifecycleObserver生命週期更新;而API29+,則會直接經過監聽Application.ActivityLifecycleCallbacks接口,進行獲取Activity的狀態,同時也會插入ReportFragment,可是該用於報告狀態的Fragment的生命週期中的dispatch將不會生效,Fragment和Activity都添加一個監聽,並在onStop先後添加輸出,兩種方式(API29+和API29如下)的回調順序也是不一樣的。

附:官方文檔部分截取

原文地址:處理 ON_STOP 事件(Google的連接不必定能打開)

1. 處理 ON_STOP 事件

若是 Lifecycle 屬於 AppCompatActivityFragment,那麼調用 AppCompatActivityFragmentonSaveInstanceState() 時,Lifecycle 的狀態會更改成 CREATED 而且會分派 ON_STOP 事件。

經過 onSaveInstanceState() 保存 FragmentAppCompatActivity 的狀態後,其界面被視爲不可變,直到調用 ON_START。若是在保存狀態後嘗試修改界面,極可能會致使應用的導航狀態不一致,所以應用在保存狀態後運行 FragmentTransaction 時,FragmentManager 會拋出異常。**如需瞭解詳情,請參閱 commit()

LiveData 自己可防止出現這種極端狀況,方法是在其觀察者的關聯 Lifecycle 尚未至少處於 STARTED狀態時避免調用其觀察者。在後臺,它會在決定調用其觀察者以前調用 isAtLeast()

遺憾的是,AppCompatActivityonStop() 方法會在 onSaveInstanceState() 以後調用,這樣就會留下一個缺口,即不容許界面狀態發生變化,但 Lifecycle 還沒有移至 CREATED 狀態。

爲防止出現這個問題,beta2 及更低版本中的 Lifecycle 類會將狀態標記爲 CREATED 而不分派事件,這樣一來,即便未分派事件(直到系統調用 onStop()),檢查當前狀態的代碼也會得到實際值。

遺憾的是,此解決方案有兩個主要問題:

  • 在 API 23 及更低級別,Android 系統實際上會保存 Activity 的狀態,即便它的一部分被另外一個 Activity 覆蓋。換句話說,Android 系統會調用 onSaveInstanceState(),但不必定會調用 onStop()。這樣可能會產生很長的時間間隔,在此時間間隔內,觀察者仍認爲生命週期處於活動狀態,雖然沒法修改其界面狀態。
  • 任何要向 LiveData 類公開相似行爲的類都必須實現由 Lifecycle 版本 beta 2 及更低版本提供的解決方案。

注意:爲了簡化此流程並讓其與較低版本實現更好的兼容性,自 1.0.0-rc1 版本起,當調用 onSaveInstanceState() 時,會將 Lifecycle 對象標記爲 CREATED 並分派 ON_STOP,而不等待調用 onStop() 方法。這不太可能影響您的代碼,但您須要注意這一點,由於它與 API 26 及更低級別的 Activity類中的調用順序不符。

2. 生命週期感知型組件的最佳作法

  • 使界面控制器(Activity 和 Fragment)儘量保持精簡。它們不該試圖獲取本身的數據,而應使用 ViewModel 執行此操做,並觀察 LiveData 對象以將更改體現到視圖中。
  • 設法編寫數據驅動型界面,對於此類界面,界面控制器的責任是隨着數據更改而更新視圖,或者將用戶操做通知給 ViewModel
  • 將數據邏輯放在 ViewModel 類中。ViewModel 應充當界面控制器與應用其他部分之間的鏈接器。不過要注意,ViewModel 不負責獲取數據(例如,從網絡獲取)。可是,ViewModel 應調用相應的組件來獲取數據,而後將結果提供給界面控制器。
  • 使用數據綁定在視圖與界面控制器之間維持乾淨的接口。這樣一來,您可使視圖更具聲明性,並儘可能減小須要在 Activity 和 Fragment 中編寫的更新代碼。若是您更願意使用 Java 編程語言執行此操做,請使用諸如 Butter Knife 之類的庫,以免樣板代碼並實現更好的抽象化。
  • 若是界面很複雜,不妨考慮建立 presenter 類來處理界面的修改。這多是一項艱鉅的任務,但這樣作可以使界面組件更易於測試。
  • 避免在 ViewModel 中引用 ViewActivity 上下文。若是 ViewModel 存在的時間比 Activity 更長(在配置更改的狀況下),Activity 將泄漏而且不會得到垃圾回收器的妥善處置。
  • 使用 Kotlin 協程管理長時間運行的任務和其餘能夠異步運行的操做。
相關文章
相關標籤/搜索