Jetpack第二篇:Lifecycles

1、什么是Lifecycles

在Jetpack中有个非常重要的概念:生命周期
比如说:LiveData,ViewMode,这些都依赖生命周期。常用的具有生命周期的组件那当然是Activity和Fragment。Lifecycles具有Activity/Fragment生命周期感知能力的组件,它能持有生命周期的状态信息,是Jetpack的核心基础。

2、Lifecycle的基本使用

Lifecycle是具有生命周期感知的组件,所以它的基本使用就是获取Activity/Fragment的生命周期状态。

  • 导入依赖
 // lifecycle组件依赖
    implementation 'androidx.lifecycle:lifecycle-common:2.2.0'

第一种方式:实现LifecycleObserver,并通过注解的方式获取生命周期状态。

class MyLifecycleObserver : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onStart(@NotNull owner: LifecycleOwner) {
        Log.i("MyLifecycleObserver", "activity onStart")
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onStop() {
        Log.i("MyLifecycleObserver", "activity onStop")
    }
}

第二种方式:实现LifecycleEventObserver,通过onStateChanged回调获取生命周期状态。

// 2、继承LifecycleEventObserver
class MyLifecycleObserver2 : LifecycleEventObserver {
    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        when (event) {
            Lifecycle.Event.ON_START -> {
                Log.i("MyLifecycleObserver2", "activity onStart: $event")
            }
            Lifecycle.Event.ON_STOP -> {
                Log.i("MyLifecycleObserver2", "activity onStop: $event")
            }
        }
    }
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        lifecycle.addObserver(MyLifecycleObserver())
        lifecycle.addObserver(MyLifecycleObserver2())
    }
}

启动Activity,然后关闭获取到的生命周期情况:

... I/MyLifecycleObserver: activity onStart
... I/MyLifecycleObserver2: activity onStart: ON_START
... I/MyLifecycleObserver2: activity onStop: ON_STOP
... I/MyLifecycleObserver: activity onStop

3、Lifecycle的源码解析

3.1、Lifecycle的关键类

LifecycleOwner

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

这是一个接口,如果要获取他的生命周期状态,那么必须实现这个接口。
Lifecycle

public abstract class Lifecycle {
}

一个抽象类,定义一些生命周期的状态枚举,以及分发状态的枚举。
LifecycleRegistry


public class LifecycleRegistry extends Lifecycle {

  // 注册Observer
  public void addObserver(@NonNull LifecycleObserver observer) {}

  // 分发生命周期事件 
  public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
  }
  
  private void moveToState(State next) {
    sync()
  }
  private void sync() {}  
}

Lifecycle的唯一实现类,主要是用于注册Observer和分发生命周期状态给Observer。

3.2、关键方法

addObserver()

@Override
    public void addObserver(@NonNull LifecycleObserver observer) {

        // 1、必须在主线程操作,否则就抛出异常。
        enforceMainThreadIfNeeded("addObserver");
        // 2、判断当前宿主(Activity/Fragment)的状态,如果是Destory则初始的状态就是Destory。其他的情况一律是Init,这里的意思就是,当前宿主是Destory,初始的状态就是Destory。其他不管宿主的状态是什么都是init。后面会同步状态。
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        // 3、将传入的observer封装成ObserverWithState。用于状态的同步和分发。
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);

        // 4、判断statefulObserver是不是已经存在mObserverMap。
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        // 5、假如这个statefulObserver已经存在了,那么就直接return
        if (previous != null) {
            return;
        }
        //6、获取宿主的LifecycleOwner对象并且判断
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            // 假如这个对象为空,那么说明这个对象已经是Destory了。返回
            return;
        }

        // 7、mAddingObserverCounter和mHandlingEvent都是确定是不是正在同步状态的判断。
        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;

        // 8、判断传入的Observer状态
        State targetState = calculateTargetState(observer);

        // 呼应7步骤,同步代码的话就++
        mAddingObserverCounter++;

        // 9、如果宿主的状态和观察者Observer不一致
        // 这里会将传入的Observer的状态和宿主状态作比较,假如不相同,传入的Observer的状态会不断升级,因为这个方法的状态一开始就是INITIALIZED,
        // 假如宿主到了onResume ,那传入的状态就会从INITIALIZED 到 onCreate 到 onResume。(这里是第一次同步状态,就是将Observer的状态和宿主的状态调成一致)
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            final Event event = Event.upFrom(statefulObserver.mState);
            if (event == null) {
                throw new IllegalStateException("no event up from " + statefulObserver.mState);
            }
            statefulObserver.dispatchEvent(lifecycleOwner, event);
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        // 则同步状态
        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }

这个mObserverMap很重要,他是判断状态是否同步的标志,我们可以看下这个putIfAbsent方法:

    @Override
    public V putIfAbsent(@NonNull K key, @NonNull V v) {
        Entry<K, V> current = get(key);
   `     if (current != null) {
    `        return current.mValue;
        }
     `   mHashMap.put(key, put(key, v));
        return null;
    }

可以看到这里会将两个值存入到一个Map中去,这里还有一个put的方法:

        mHashMap.put(key, put(key, v));
      // 这个 put(key, v)方法很重要

继续看这个put的方法:

    protected Entry<K, V> put(@NonNull K key, @NonNull V v) {
        Entry<K, V> newEntry = new Entry<>(key, v);
        mSize++;
        if (mEnd == null) {
            mStart = newEntry;
            mEnd = mStart;
            return newEntry;
        }

        mEnd.mNext = newEntry;
        newEntry.mPrevious = mEnd;
        mEnd = newEntry;
        return newEntry;
    }

从这个代码中可以看到,这里是操作单链表,这些操作可以看作把新传入的状态赋值给mStart,然mEnd就会等于mStart。
这里可以理解为:mStart为新的状态,mEnd为老的状态。
同步状态并分发状态:


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) {
                backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

首先得看下isSynced方法,可以看到这里比较了mObserverMap的eldest和newest。然后两者如果不一致则代表未同步。如果再往里面寻找,则可以发现这个实际上就是比较上面说到的mStart和mEnd的值。

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

分发状态,不论是backwardpass() 还是 forwardPass() 最后调用的都是:

observer.dispatchEvent(lifecycleOwner, event);
    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = event.getTargetState();
        mState = min(mState, newState);
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}

前面的代码中提到了,注册的Observer会封装成ObserverWithState,这个负责状态事件的分发。

3.3、Activity如何实现Lifecycle?

从上小节知道,假如Activity需要实现Observer,那么需要实现LifcycleOwner. 寻找到根源,可以看到ComponentActivity,实现了LifecycleOwner。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        ContextAware,
        LifecycleOwner,
{
        }

直接看onCreate的代码:有一个ReportFragment。


  /**
     * {@inheritDoc}
     *
     * If your ComponentActivity is annotated with {@link ContentView}, this will
     * call {@link #setContentView(int)} for you.
     */
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {

         /// ... ...
        ReportFragment.injectIfNeededIn(this);
    }

injectIfNeededIn这个LifecycleCallbacks.registerIn(activity)看起来和Lifecycle有关。


  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);
        }
        // ... ...
         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();
        }
    }

这里有个很明显的版本判断,当sdk大于29时

LifecycleCallbacks.registerIn(activity);

当sdk小于等于29一定会走:

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

先了解关于Activity和Fragment混合使用的生命周期使用方式:
就是相当于Activity中初始化一个Fragment通过Fragment的生命周期去回调Activity的生命周期。
所以在ReportFragment中就可以看到这样的代码。dispatch()方法非常重要

 @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

然后就绕到了moveToState方法中了,第二节就说明了,这个东西就是同步状态,回调生命周期的方法。
那么当sdk>29时呢?


@RequiresApi(29)
static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {

    static void registerIn(Activity activity) {
        activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
    }

    @Override
    public void onActivityCreated(@NonNull Activity activity,
            @Nullable Bundle bundle) {
    }

    @Override
    public void onActivityPostCreated(@NonNull Activity activity,
            @Nullable Bundle savedInstanceState) {
        dispatch(activity, Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onActivityStarted(@NonNull Activity activity) {
    }

    @Override
    public void onActivityPostStarted(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_START);
    }

    @Override
    public void onActivityResumed(@NonNull Activity activity) {
    }

    @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 onActivityPaused(@NonNull Activity activity) {
    }

    @Override
    public void onActivityPreStopped(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onActivityStopped(@NonNull Activity activity) {
    }

    @Override
    public void onActivitySaveInstanceState(@NonNull Activity activity,
            @NonNull Bundle bundle) {
    }

    @Override
    public void onActivityPreDestroyed(@NonNull Activity activity) {
        dispatch(activity, Lifecycle.Event.ON_DESTROY);
    }

    @Override
    public void onActivityDestroyed(@NonNull Activity activity) {
    }
}

当sdk>29时,Activity会注册一个回调,Activity的生命周期就中就会掉用这里的回调,然后调用dispatch同步状态。
这些状态都在Activity回调。

private void dispatchActivityPostStarted() {
    Object[] callbacks = collectActivityLifecycleCallbacks();
    if (callbacks != null) {
        for (int i = 0; i < callbacks.length; i++) {
            ((Application.ActivityLifecycleCallbacks) callbacks[i])
                    .onActivityPostStarted(this);
        }
    }
    getApplication().dispatchActivityPostStarted(this);
}

private void dispatchActivityPreResumed() {
    getApplication().dispatchActivityPreResumed(this);
    Object[] callbacks = collectActivityLifecycleCallbacks();
    if (callbacks != null) {
        for (int i = 0; i < callbacks.length; i++) {
            ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(this);
        }
    }
}
3.4、Fragment如何实现Lifecycle

相比较Activity的实现方式,Fragment的实现方式就简单很多

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner, HasDefaultViewModelProviderFactory, SavedStateRegistryOwner,
        ActivityResultCaller {
        }

LifecycleRegistry mLifecycleRegistry;

    public Fragment() {
        initLifecycle();
    }

private void initLifecycle() {
        mLifecycleRegistry = new LifecycleRegistry(this);
        mSavedStateRegistryController = SavedStateRegistryController.create(this);
}
    void performStart() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }

    void performStop() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
    }

有个LifecycleRegistry的成员变量,Fragment构造函数中初始化,然后在每一个生命周期回调中都会调用HandleLifecycleEvent,前面就提到了,HandleLifecycleEvent会调用movetostate() sync() 然后分发事件。

4、写在最后

上面这么多的源码,最后总结一下这些关键的点:

  • 一定要知道关键的三个类LifecycleOwner、Lifecycle、LifecycleRegistry这三个类在这个系统中具体的作用
  • 写一个基本的Lifecycle
  • Activity29以上是通过回调来分发状态,29一下是通过ReportFragment来分发状态。
  • Fragment的状态分发是直接通过生命周期的回调来分发。
  • 了解LifecycleRegistry的注册Observer方法,分发事件的方法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容