Android Architecture Component -- Lifecycle 浅析

2,348 阅读3分钟

Lifecycle

LifecycleAndroid Architecture Components 的一个组件,用于将系统组件(Activity、Fragment 等等)的生命周期分离到 Lifecycle 类,Lifecycle 类允许其他类作为观察者,在外部观察系统组件生命周期的变化。Lifecycle 用起来很简单,首先声明一个 LifecycleObserver 对象,用 @OnLifecycleEvent 注解声明生命周期事件回调的方法:

public class LifecycleObserverDemo implements LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onAny(LifecycleOwner owner, Lifecycle.Event event) {
        System.out.println("onAny:" + event.name());
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreate() {
        System.out.println("onCreate");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy() {
        System.out.println("onDestroy");
    }
}

然后在 LifecycleRegistryOwner 比如 LifecycleActivity 加入这么一行代码:

    getLifecycle().addObserver(new LifecycleObserverDemo());

然后?然后就没然后了,运行起来可以看到 LifecycleActivity 的生命周期发生变化时,LifecycleObserverDemo 总能得到通知。而 LifecycleActivity 只有寥寥几行代码,并没有覆盖任何回调方法。那么 Lifecycle 是怎么做到的,是不是有点黑魔法的感觉?

注解的作用

首先从注解入手,可以在 build 目录下发现注解处理器为我们生成了 LifecycleObserverDemo_LifecycleAdapter,不过这只是一个适配器,用于将生命周期事件派发到 LifecycleObserverDemo 对应的方法。

public class LifecycleObserverDemo_LifecycleAdapter implements GenericLifecycleObserver {
  final LifecycleObserverDemo mReceiver;

  LifecycleObserverDemo_LifecycleAdapter(LifecycleObserverDemo receiver) {
    this.mReceiver = receiver;
  }

  @Override
  public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) {
    mReceiver.onAny(owner,event);
    if (event == Lifecycle.Event.ON_CREATE) {
      mReceiver.onCreate();
    }
    if (event == Lifecycle.Event.ON_START) {
      mReceiver.onStart();
    }
    if (event == Lifecycle.Event.ON_PAUSE) {
      mReceiver.onPause();
    }
    if (event == Lifecycle.Event.ON_DESTROY) {
      mReceiver.onDestroy();
    }
  }

  public Object getReceiver() {
    return mReceiver;
  }
}

如何传达 lifecycle 事件

Activity 不用写任何代码,那么 Lifecycle 是如何把 Activity 生命周期事件传递给 LifecycleObserver?最终通过研读 Lifecycle 的代码,发现里面有个包可见的类 LifecycleDispatcherLifecycleDispatcher 是一个单例,在 LifecycleDispatcher#init(Context) 中,它通过 registerActivityLifecycleCallbacks 方法,向当前的 Application 注册一个 DispatcherActivityCallback,但 Lifecycle 并没使用 ActivityLifecycleCallbacks 来监听并派发生命周期事件。

static void init(Context context){
    ...
    ((Application)context.getApplicationContext()).registerActivityLifecycleCallbacks(new LifecycleDispatcher.DispatcherActivityCallback());
    ...
}

static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        ...
        if(manager.findFragmentByTag("android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag") == null) {
            manager.beginTransaction().add(new ReportFragment(), "android.arch.lifecycle.LifecycleDispatcher.report_fragment_tag").commit();
            manager.executePendingTransactions();
        }
    }
}

而是通过一个无 UI 的 Fragment,在 DispatcherActivityCallback#onActivityCreated 可以看到它在 Activity#onCreate 时,为 Activity 添加一个 ReportFragment。最终由 ReportFragment 来监听各个生命周期事件,然后传递给 LifecycleRegistry

public class ReportFragment extends Fragment {
    ...
    public void onPause() {
        super.onPause();
        dispatch(Event.ON_PAUSE);
    }
    ...
    private void dispatch(Event event) {
        if(this.getActivity() instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner)this.getActivity()).getLifecycle().handleLifecycleEvent(event);
        }
    }
}

Activity 的生命周期事件都会派发到它的 Fragments,向 Activity 注册一个无 UI 的 Fragment 用于将各种 Activity 回调分离出来是个常用的做法,比如 RxPermissions 也是用这种方法来避免覆盖 Activity#onRequestPermissionsResult 或者引入 ShadowActivity 之类的 hack。

顺便一提 Lifecycle 文档提到:

ON_CREATE, ON_START, ON_RESUME events in this class are dispatched after the LifecycleOwner's related method returns. ON_PAUSE, ON_STOP, ON_DESTROY events in this class are dispatched before the LifecycleOwner's related method is called.

正好是 Fragment 生命周期回调的触发顺序。

终于 Activity 的生命周期变化是如何传递到 LifecycleObserver 有了清晰的图表:


生命周期传递到 LifecycleObserver

LifecycleRuntimeTrojanProvider

还有一个问题, LifecycleDispatcher#init(Context) 并不是入口,它也需要被调用。那么他的调用者是谁?Google 这里的做法还是很巧妙的,如果把 apk 的 AndroidManifest.xml 提取出来,就会发现多了一个 ContentProvider 声明:

<provider
        android:name="android.arch.lifecycle.LifecycleRuntimeTrojanProvider"
        android:authorities="${applicationId}.lifecycle-trojan"
        android:exported="false"
        android:multiprocess="true" />

LifecycleRuntimeTrojanProvider 运行时木马是什么鬼?实际上,它不是一个 ContentProvider,而是利用 ContentProvider 的特点在应用程序初始化时,向应用注入两行代码:

LifecycleDispatcher.init(getContext());
ProcessLifecycleOwner.init(getContext());

这里 ContentProvider 之于 Application 的作用就类似于无 UI Fragment 之于 Activity 一样,目的都是避免继承系统组件。关于 ContentProvider 的生命周期可以看 android - ContentProvider destruction/lifecycle - Stack Overflow

其他 LifecycleOnwer

另外再提一下,Lifecycle 还提供了内置了另外三个 LifecycleOnwer:

  1. LifecycleFragment
  2. LifecycleService,ServiceLifecycleDispatcher 将事件派发重新推到主线程消息队列,用于保证确保回调在 Service 生命周期回调后再调用。
  3. ProcessLifecycleOwner,用于监听整个应用的前后台切换。也是利用 ActivityLifecycleCallback 监听每个 Activity 的生命周期,如果 onStop 事件后,没有监听到任意的 onStart 事件,那么 ProcessLifecycleOwner 就会认为整个应用切换到后台,同时留下一个标志。如果监听到 onStart 事件,同时检查有标志那么就会认为应用回到前台。