JetPacks之Lifecycles原理

JetPacks之Lifecycles原理
項(xiàng)目資源
UML 時(shí)序圖

讀懂這里,查看下一篇 LiveDataBus
下一篇LiveData

預(yù)備知識點(diǎn)

<LifeCycles> 「觀察者模式- 反射 - 注解」

源碼結(jié)構(gòu)

Lifecycle 類是abstract

  -> 留意一下這幾個狀態(tài)褪贵,下面會有用
 public enum Event {
    /**
     * Constant for onCreate event of the {@link LifecycleOwner}.
     */
    ON_CREATE,
    /**
     * Constant for onStart event of the {@link LifecycleOwner}.
     */
    ON_START,
    /**
     * Constant for onResume event of the {@link LifecycleOwner}.
     */
    ON_RESUME,
    /**
     * Constant for onPause event of the {@link LifecycleOwner}.
     */
    ON_PAUSE,
    /**
     * Constant for onStop event of the {@link LifecycleOwner}.
     */
    ON_STOP,
    /**
     * Constant for onDestroy event of the {@link LifecycleOwner}.
     */
    ON_DESTROY,
    /**
     * An {@link Event Event} constant that can be used to match all events.
     */
    ON_ANY
}


public enum State {
    
    DESTROYED,

    INITIALIZED,

    CREATED,

    STARTED,

    RESUMED;

    public boolean isAtLeast(@NonNull State state) {
        return compareTo(state) >= 0;
    }
}

看下我們的Activity 的關(guān)系

AppCompatActivity extends FragmentActivity implements AppCompatCallback,
    TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider 
...
public class FragmentActivity extends ComponentActivity implements
    ActivityCompat.OnRequestPermissionsResultCallback,
    ActivityCompat.RequestPermissionsRequestCodeValidator {
...

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
    LifecycleOwner,
    ViewModelStoreOwner,
    SavedStateRegistryOwner,
    OnBackPressedDispatcherOwner {
...

【自定義測試代碼】用一段測試代碼作為入口點(diǎn)渺尘,查看我們的源代碼

public class NameActivity extends AppCompatActivity {

private NameViewModel model;

private TextView nameTextView;
private Button btn;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_name);
    nameTextView=findViewById(R.id.tvText);
    btn=findViewById(R.id.btn);

    model= ViewModelProviders.of(this).get(NameViewModel.class);

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

    //訂閱
    model.getCurrentName().observe(this,observer);

    btn.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            String anotherName="Jetpack"+(model.i++);
            model.getCurrentName().setValue(anotherName);
        }
    });

}

}

看下我們activity_name 布局敛助,為了方便我們就按照最簡單的來寫

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
    android:id="@+id/tvText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
     />

<Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
     />
</LinearLayout>

我們來找到兩個閱讀源碼的入口點(diǎn)

    //訂閱
    ->  源碼入口點(diǎn)1
    model.getCurrentName().observe(this,observer);

    btn.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v) {
            String anotherName="Jetpack"+(model.i++);
            ->  源碼入口點(diǎn)2
            model.getCurrentName().setValue(anotherName);
        }
    });

記錄好這兩個入口使用點(diǎn)骚勘,我們回頭再來看這里

進(jìn)入 源碼ComponentActivity

構(gòu)造方法:

我們知道有一個兼容處理

ComponentActivity()  {   
...
if (19 <= SDK_INT && SDK_INT <= 23) {
        getLifecycle().addObserver(new ImmLeaksCleaner(this));
    }
}

真正重要的是onCreate

-> 關(guān)注一下「ReportFragment」
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    ...
    ReportFragment.injectIfNeededIn(this);
    ...
}

ReportFragment

進(jìn)入方法我們看到虹茶,和Glide等源碼框架思路一致刀森,創(chuàng)建一個沒有布局的fragment

public static void injectIfNeededIn(Activity activity) {
    if (Build.VERSION.SDK_INT >= 29) {
        // On API 29+, we can register for the correct Lifecycle callbacks directly
        activity.registerActivityLifecycleCallbacks(
                new LifecycleCallbacks());
    }
   
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
        manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
        // Hopefully, we are the first to make a transaction.
        manager.executePendingTransactions();
    }
}

進(jìn)入初始化方法查看

  -> 關(guān)注一下源代碼 「分發(fā)事件 」dispatch(Lifecycle.Event.xxx)
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    dispatchCreate(mProcessListener);
    dispatch(Lifecycle.Event.ON_CREATE);
}

@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);
}

@Override
public void onStop() {
    super.onStop();
    dispatch(Lifecycle.Event.ON_STOP);
}

@Override
public void onDestroy() {
    super.onDestroy();
    dispatch(Lifecycle.Event.ON_DESTROY);
    // just want to be sure that we won't leak reference to an activity
    mProcessListener = null;
}

我們進(jìn)入dipatch方法一探究竟「可能29+ 走的是回調(diào)結(jié)構(gòu)踱启,但差不多」

-> 發(fā)現(xiàn)最終都是走的 handleLifecycleEvent,進(jìn)入方法看看
    
@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);
        }
    }
}

handleLifecycleEvent

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    -> 拿到下一個周期的狀態(tài),并將狀態(tài)移動
    State next = getStateAfter(event);
    -> 移動到下一個狀態(tài)研底,分別進(jìn)入這兩個方法查看一下
    moveToState(next);
}

getStateAfter(event) ------------------------>

-> 看到下面代碼狀態(tài)對應(yīng)的值埠偿,相信都能看懂
static State getStateAfter(Event event) {
    switch (event) {
        case ON_CREATE:
        case ON_STOP:
            return CREATED;
        case ON_START:
        case ON_PAUSE:
            return STARTED;
        case ON_RESUME:
            return RESUMED;
        case ON_DESTROY:
            return DESTROYED;
        case ON_ANY:
            break;
    }
    throw new IllegalArgumentException("Unexpected event value " + event);
}

來一張圖描述


時(shí)序圖

moveToState ---------->

private void moveToState(State next) {
    if (mState == next) {
        return;
    }
    mState = next;
    if (mHandlingEvent || mAddingObserverCounter != 0) {
        mNewEventOccurred = true;
        // we will figure out what to do on upper level.
        return;
    }
    mHandlingEvent = true;
    ->關(guān)注這個方法,再次進(jìn)入看下
    sync();
    mHandlingEvent = false;
}

在這個各方發(fā)里面榜晦,如上圖某個狀態(tài)的冠蒋,對應(yīng)的會有 backwardPass(lifecycleOwner),forwardPass(lifecycleOwner);
當(dāng)前處于的狀態(tài)和程序目標(biāo)狀態(tài)同步出現(xiàn)差異乾胶,會進(jìn)行移動

private void sync() {
    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.");
    }
    while (!isSynced()) {
        mNewEventOccurred = false;
        // no need to check eldest for nullability, because isSynced does it for us.
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {

            -> 關(guān)注這兩個方法實(shí)現(xiàn)差不多抖剿,隨便找一個點(diǎn)進(jìn)去查看==

            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {

            -> 關(guān)注這兩個方法實(shí)現(xiàn)差不多统屈,隨便找一個點(diǎn)進(jìn)去查看==

            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

forwardPass----------------->dispatchEvent

    private void forwardPass(LifecycleOwner lifecycleOwner) {
    Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
            mObserverMap.iteratorWithAdditions();
    while (ascendingIterator.hasNext() && !mNewEventOccurred) {
        Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
        ObserverWithState observer = entry.getValue();
        while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            pushParentState(observer.mState);

            -> dispatchEvent 關(guān)鍵看下這個

            observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
            popParentState();
        }
    }
}

你會發(fā)現(xiàn)走了一個靜態(tài)內(nèi)部類回調(diào)-----》onStateChanged

static class ObserverWithState {
    。牙躺。愁憔。

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        -> 注意跟蹤這里
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}

調(diào)用了【實(shí)現(xiàn)接口的方法類】

class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver {
private final Object mWrapped;
private final CallbackInfo mInfo;

ReflectiveGenericLifecycleObserver(Object wrapped) {
    mWrapped = wrapped;
    mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
}

@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) {
    mInfo.invokeCallbacks(source, event, mWrapped);
}

}

進(jìn)入構(gòu)造方法,你會看到重要的一句

        OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);

這就是我們卸載自己的周期函數(shù)上的類注解孽拷。我們通過APT 反射方法獲取相關(guān)詳情

執(zhí)行反射onStateChanged

承接最開始吨掌,我們記錄的。
-> 源碼入口點(diǎn)1
model.getCurrentName().observe(this,observer);

跟進(jìn)去脓恕,我們會看程序進(jìn)入onStateChange

observe->owner.getLifecycle().addObserver(wrapper);
->addObserver

pushParentState(statefulObserver.mState);
->        statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
        popParentState();

-> mLifecycleObserver.onStateChanged(owner, event);

進(jìn)入 ReflectiveGenericLifecycleObserver

-> 源碼入口點(diǎn)2
model.getCurrentName().setValue(anotherName);

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

跟進(jìn)

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            -> 關(guān)鍵看這個點(diǎn)
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                  -> 關(guān)鍵看這個點(diǎn)
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

看下重要的version比對點(diǎn)膜宋,最終調(diào)用onChange 接口,我們自己的實(shí)現(xiàn)炼幔。整個觀察者閉環(huán)走完

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載秋茫,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末乃秀,一起剝皮案震驚了整個濱河市肛著,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跺讯,老刑警劉巖枢贿,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異刀脏,居然都是意外死亡局荚,警方通過查閱死者的電腦和手機(jī)诱建,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進(jìn)店門峻凫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞬项,“玉大人黍檩,你說我怎么就攤上這事汽馋≡祝” “怎么了厉膀?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵逃延,是天一觀的道長擎析。 經(jīng)常有香客問我簿盅,道長,這世上最難降的妖魔是什么揍魂? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任桨醋,我火速辦了婚禮,結(jié)果婚禮上现斋,老公的妹妹穿的比我還像新娘喜最。我一直安慰自己,他們只是感情好庄蹋,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布瞬内。 她就那樣靜靜地躺著迷雪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虫蝶。 梳的紋絲不亂的頭發(fā)上章咧,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天,我揣著相機(jī)與錄音能真,去河邊找鬼赁严。 笑死,一個胖子當(dāng)著我的面吹牛粉铐,可吹牛的內(nèi)容都是我干的疼约。 我是一名探鬼主播,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼蝙泼,長吁一口氣:“原來是場噩夢啊……” “哼程剥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汤踏,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤织鲸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后茎活,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昙沦,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年载荔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片采桃。...
    茶點(diǎn)故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡懒熙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出普办,到底是詐尸還是另有隱情工扎,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布衔蹲,位于F島的核電站肢娘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏舆驶。R本人自食惡果不足惜橱健,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沙廉。 院中可真熱鬧拘荡,春花似錦、人聲如沸撬陵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蟋定,卻和暖如春粉臊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驶兜。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工维费, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人促王。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓犀盟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蝇狼。 傳聞我的和親對象是個殘疾皇子阅畴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評論 2 361