JetPack之Lifecycle使用和原理

什么是Lifecycle

远古时代

在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的工作流程:

我们可以通过在代码使用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的最佳实践

  • 使界面控制器(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>),应用可以在用户使用位置发生变化时自动更新界面。
  • 停止和开始视频缓冲。使用生命周期感知型组件可尽快开始视频缓冲,但会推迟播放,直到应用完全启动。此外,应用销毁后,您还可以使用生命周期感知型组件终止缓冲。
  • 开始和停止网络连接。借助生命周期感知型组件,可在应用位于前台时启用网络数据的实时更新(流式传输),并在应用进入后台时自动暂停。
  • 暂停和恢复动画可绘制资源。借助生命周期感知型组件,可在应用位于后台时暂停动画可绘制资源,并在应用位于前台后恢复可绘制资源。