JetPack基本组件一:Lifecycle

JetPack基本组件一:Lifecycle

LifeCycle

前言

Hello大家好,这里是BlueLzy。本文是JetPack全家桶系列文章的第一篇。作为一名Android开发者,在2021年必备的技能之一就是熟练使用Google为我们提供的开发组件,这一套组件的名字就是:JetPack。里面包括了许多不同功能的SDK,Google推出这套开发组件的目的就是为了能够让开发者在遵循Android系统的生命周期的同时,写出Bug更少,代码量更少,性能更好的App。

因此,这一系列文章会按照下面的顺序来介绍其中几个最主要的组件,在学习完这些基本组件之后,通过一个小项目在实践中学习API的时候,领会SDK的设计思想和原理等等。达到学以致用的目的。

下面是系列文章的目录:

  1. Lifecycle - 生命周期感知型组件
  2. LiveData - 可观察的数据存储器类
  3. ViewModel - 结合LiveData和LifeCycle的数据管理组件
  4. DataBinding - 声明式数据驱动UI组件

除了上面介绍了这几个组件,JetPack其实还提供了其他许多组件,包括:WorkManager,Navigation,Paging等等

我们可以通过Google的官方网站进行查阅:

本文目录

什么是Lifecycle

一般来说,无论是Github上优秀的开源库,还是Google推出的新技术,都是为了解决旧的技术遗留的历史问题,也就是说,我们在学习新技术的时候,不仅要学会如何使用API,还要思考“为什么要有这个技术?”,“它和之前的解决方案相比,有什么优势?”

当然,要知道“Why”,首先还是要知道“What”和“How”。知其然,知其所以然。

远古时代

在Android开发中,我们需要遵循组件的生命周期,例如在onStart()onResume()的时候更新UI,在onStop()onDestroy()的时候停止后台任务和释放资源。

举个常见的例子:我们需要在Activity的生命周期到底onCreate()的时候调用接口请求数据,然后在onResume()的时候设置到UI界面中,并且在onStop()的时候停止请求,否则有可能会出现内存泄漏的情况。

class MyActivity : AppCompatActivity() {
    private lateinit var request: MainRequset

        private var data: List<String> = mutableListOf()

    override fun onCreate(...) {
        request= MainRequset(this) { list ->
            // update UI
                        data = list
        }
    }

    public override fun onResume() {
        super.onStart()
        textView.setText(data[0])
    }

    public override fun onStop() {
        super.onStop()
        request.stop()
    }

}

随着项目不断迭代,需要在生命周期的不同阶段做的任务也越来越多,导致了这几个生命周期方法里面的业务代码越来越臃肿,最后接手的开发者难以维护。

class MyActivity : AppCompatActivity() {
    private lateinit var request: MainRequest // 首页数据
        private lateinit var firebase: FireBase  // 性能监控
        private lateinit var pushNotification: PushNotification  // 推送服务
        private lateinit var startup: SplashScreen  // 开屏广告

        private var data: List<String> = mutableListOf()

    override fun onCreate(...) {
        request = MainRequest(this) { list ->
            // update UI
                        data = list
        }

                firebase = FireBase(this) { isSucceed ->
            // do Something

        }

                pushNotification = PushNotification(this) { isSucceed->
            // do Something
        }

                startup = SplashScreen(this) { isSucceed->
            // do Something
        }
    }

    public override fun onResume() {
        super.onStart()
        textView.setText(data[0])
                //...
    }

    public override fun onStop() {
        super.onStop()
        request.stop()
                firebase.stop()
                pushNotification.stop()
                startup.stop()
    }

}

Lifecycle的出现

这里我们引用Google Developers的图来说明Lifecycle的工作流程:

Untitled

我们可以通过在代码使用LifecycleObserver和@OnLifecycleEvent注解来实现对生命周期回调方法的监听。举个例子:

class MainActivity : BaseDataBindingActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        applyExitMaterialTransform()
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        lifecycle.addObserver(testListener())
    }

    inner class testListener(): LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun start() {
            Log.d("bluelzy", "start")
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun stop() {
            Log.d("bluelzy","stop")
        }
    }

}

上面这段代码主要做了两件事:

  1. 定义了一个testListener内部类,它继承自LifecycleObserver接口,并且定义了两个方法,分别在onStart()和onStop()的时候会接收到回调
  2. 在Activity的onCreate()中通过addObserver()方法把testListener添加到观察者列表中

然后运行程序,我们可以看到Logcat中会打印出来,当MainActivity的生命周期到onStart()的时候,会调用testListener的start()方法,同样当生命周期到了onStop()的时候,会调用testListener的stop()方法。

相比起之前我们在Activity的各个生命周期方法中写一大段业务代码,是不是简化了许多?

在这里我们会有一些疑问:

  1. LifecycleObserver 是什么,观察者模式是什么运作的?
  2. Lifecycle原理是什么?为什么调用addOberver就可以观察到对应组件的生命周期了?

这些疑问需要我们从源码来解答。

Lifecycle的原理和设计思想

上面我们提出了两个问题,就是关于Lifecycle是如何运作的,它背后的原理到底是什么?我们通过源码来一步步解析。

首先Lifecycle有几个关键的类,分别是:

  • Lifecycle:抽象类,唯一子类就是LifecycleRegistry
  • LifecycleOwner:具有生命周期感知能力的类需要实现的接口
  • LifecycleOberver:Lifecycle需要观察的对象们(被观察者)
  • LifecycleRegistry:负责转发生命周期事件,Lifecycle的真正的实现类

接下来我们一个个来详细讲解。

Abstract Class: Lifecycle

Lifecycle所在路径:package androidx.lifecycle;

整个Lifecycle类再2.2.0版本只有200行代码,主要是定义了生命周期相关状态,以及Observer相关的add和remove方法。

下面是Lifecycle.java源码

public abstract class Lifecycle {

    /**
     * Lifecycle coroutines extensions stashes the CoroutineScope into this field.
     *
     * @hide used by lifecycle-common-ktx
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    @NonNull
    AtomicReference<Object> mInternalScopeRef = new AtomicReference<>();

    /**
     * Adds a LifecycleObserver that will be notified when the LifecycleOwner changes
     * state.
     * <p>
     * The given observer will be brought to the current state of the LifecycleOwner.
     * For example, if the LifecycleOwner is in {@link State#STARTED} state, the given observer
     * will receive {@link Event#ON_CREATE}, {@link Event#ON_START} events.
     *
     * @param observer The observer to notify.
     */
    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);

    /**
     * Removes the given observer from the observers list.
     * <p>
     * If this method is called while a state change is being dispatched,
     * <ul>
     * <li>If the given observer has not yet received that event, it will not receive it.
     * <li>If the given observer has more than 1 method that observes the currently dispatched
     * event and at least one of them received the event, all of them will receive the event and
     * the removal will happen afterwards.
     * </ul>
     *
     * @param observer The observer to be removed.
     */
    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);

    /**
     * Returns the current state of the Lifecycle.
     *
     * @return The current state of the Lifecycle.
     */
    @MainThread
    @NonNull
    public abstract State getCurrentState();

    @SuppressWarnings("WeakerAccess")
    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
    }

    /**
     * Lifecycle states. You can consider the states as the nodes in a graph and
     * {@link Event}s as the edges between these nodes.
     */
    @SuppressWarnings("WeakerAccess")
    public enum State {
        /**
         * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch
         * any more events. For instance, for an {@link android.app.Activity}, this state is reached
         * <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call.
         */
        DESTROYED,

        /**
         * Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is
         * the state when it is constructed but has not received
         * {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet.
         */
        INITIALIZED,

        /**
         * Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state
         * is reached in two cases:
         * <ul>
         *     <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;
         *     <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call.
         * </ul>
         */
        CREATED,

        /**
         * Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state
         * is reached in two cases:
         * <ul>
         *     <li>after {@link android.app.Activity#onStart() onStart} call;
         *     <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call.
         * </ul>
         */
        STARTED,

        /**
         * Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state
         * is reached after {@link android.app.Activity#onResume() onResume} is called.
         */
        RESUMED;

        /**
         * Compares if this State is greater or equal to the given {@code state}.
         *
         * @param state State to compare with
         * @return true if this State is greater or equal to the given {@code state}
         */
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }

可以看到,主要定义了两个枚举类型,分别为Event和State,这两者都和生命周期方法回调相对应。可以参考上面的图。

举个例子:

Activity的生命周期走了onStart()方法,这时候会触发ON_START事件(Event),并且对应的状态(State)也会变成STARTED。这个状态在LiveData是否进行回调的时候会用到。

Interface: LifecycleObserver

public interface LifecycleObserver {

}

没有任何方法的一个空接口,所有实现了这个接口的类本质上都具有对生命周期的“被”观察能力。它们在生命周期方法回调的时候,在LifecycleRegistry中会进行分发。

Interface: LifecycleOwner

public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     *
     * @return The lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

这个类是一个接口,里面只有一个方法,就是getLifecycle(),返回Lifecycle对象。无论是Activity还是Fragment,都实现了这个接口,而他们返回的Lifecycle对象,就是LifecycleRegistry

Class: LifecycleRegistry

接下来看看LifecycleRegistry,它作为Lifecycle唯一的实现类,承载了生命周期分发的职责。

在Lifecycle里面通过addObserver()方法添加的LifecycleObserver,都会进行生命周期分发。

private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>()

@MainThread
    public void setCurrentState(@NonNull State state) {
        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.
     *
     * @param event The event that was received
     */
    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }

    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;
        sync();
        mHandlingEvent = false;
    }

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

主要的方法就是handleLifecycleEvent(),在通过getStateAfter()把Event转为State之后进行分发

在分发之前,还需要做一步操作,

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

可以看到,在sync()方法里面,还要判断当前State。

  • 如果当前State小于ObserverMap的状态,说明当前生命周期组件状态需要“降级”
  • 如果当前State大于ObserverMap的状态,说明当前生命周期组件状态需要“升级”

关于“升级”和“降级”的方法可以看下面代码:

@Nullable
public static Event downFrom(@NonNull State state) {
    switch (state) {
  case CREATED:
    return ON_DESTROY;
  case STARTED:
    return ON_STOP;
  case RESUMED:
    return ON_PAUSE;
  default:
    return null;
  }
}

@Nullable
public static Event upFrom(@NonNull State state) {
  switch (state) {
    case INITIALIZED:
      return ON_CREATE;
    case CREATED:
      return ON_START;
    case STARTED:
      return ON_RESUME;
     default:
       return null;
   }
}

举个例子:当前Activity的生命周期到了onCreate(),然后需要进行生命周期事件分发,这时候生命周期是STARTED,但是mState还是INITIALIZED,因此需要执行forwardPass()。

执行结束之后再进行生命周期事件分发:

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);
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
            }
        }
    }

    private void backwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
        while (descendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                Event event = downEvent(observer.mState);
                pushParentState(getStateAfter(event));
                observer.dispatchEvent(lifecycleOwner, event);
                popParentState();
            }
        }

分发的方法就是:dispatchEvent()

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

到这里为止,整个Lifecycle的生命周期分发过程就讲解完了。大家跟着源码读一遍的话思路还是挺清晰的。有什么疑问欢迎评论区随时留言~

下面还从Android Developer官方摘抄了一些最佳实践的提示。

总结

Lifecycle的最佳实践

  • 使界面控制器(Activity 和 Fragment)尽可能保持精简。它们不应试图获取自己的数据,而应使用 [ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) 执行此操作,并观察 [LiveData](https://developer.android.com/reference/androidx/lifecycle/LiveData) 对象以将更改体现到视图中。
  • 设法编写数据驱动型界面,对于此类界面,界面控制器的责任是随着数据更改而更新视图,或者将用户操作通知给 [ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
  • 将数据逻辑放在 [ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) 类中。[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) 应充当界面控制器与应用其余部分之间的连接器。不过要注意,[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) 不负责获取数据(例如,从网络获取)。但是,[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) 应调用相应的组件来获取数据,然后将结果提供给界面控制器。
  • 使用数据绑定在视图与界面控制器之间维持干净的接口。这样一来,您可以使视图更具声明性,并尽量减少需要在 Activity 和 Fragment 中编写的更新代码。如果您更愿意使用 Java 编程语言执行此操作,请使用诸如 Butter Knife 之类的库,以避免样板代码并实现更好的抽象化。
  • 如果界面很复杂,不妨考虑创建 presenter 类来处理界面的修改。这可能是一项艰巨的任务,但这样做可使界面组件更易于测试。
  • 避免在 [ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel) 中引用 [View](https://developer.android.com/reference/android/view/View) 或 [Activity](https://developer.android.com/reference/android/app/Activity) 上下文。如果 ViewModel 存在的时间比 activity 更长(在配置更改的情况下),activity 将泄露并且不会得到垃圾回收器的妥善处置。
  • 使用 Kotlin 协程管理长时间运行的任务和其他可以异步运行的操作。

Lifecycle的使用场景

Lifecycle可使您在各种情况下更轻松地管理生命周期。下面列举几个例子:

  • 在粗粒度和细粒度位置更新之间切换。使用生命周期感知型组件可在位置应用可见时启用细粒度位置更新,并在应用位于后台时切换到粗粒度更新。借助生命周期感知型组件 [LiveData](https://developer.android.com/reference/androidx/lifecycle/LiveData),应用可以在用户使用位置发生变化时自动更新界面。
  • 停止和开始视频缓冲。使用生命周期感知型组件可尽快开始视频缓冲,但会推迟播放,直到应用完全启动。此外,应用销毁后,您还可以使用生命周期感知型组件终止缓冲。
  • 开始和停止网络连接。借助生命周期感知型组件,可在应用位于前台时启用网络数据的实时更新(流式传输),并在应用进入后台时自动暂停。
  • 暂停和恢复动画可绘制资源。借助生命周期感知型组件,可在应用位于后台时暂停动画可绘制资源,并在应用位于前台后恢复可绘制资源。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注