阅读 932

如何绑定页面生命周期(二)-基于Android Architecture Components的Lifecycle实现

上篇文章如何绑定页面生命周期(一)-Glide实现介绍了Glide实现生命周期感知的原理,这里我们再介绍基于Android Architecture Components的Lifecycle实现页面生命周期感知。

Lifecycle是Android Architecture Components(之后简称AAC)的一个组件,用于将系统组件(Activity、Fragment等等)的生命周期分离到Lifecycle类,Lifecycle允许其他类作为观察者,观察组件生命周期的变化。

基于AAC实现组件生命周期观察实践

  • 控件实现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,比如在实现了LifecycleRegistryOwner接口的Activity中。定义LifecycleRegistry实例,并将控件lifecycleRegistry实例中的监听集合中。
public class MainActivity extends AppCompatActivity implements LifecycleRegistryOwner {
	// 定义LifecycleRegistry实例
    private LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 加入监听集合
        getLifecycle().addObserver(new LifecycleObserverDemo());        
    }

    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}
复制代码

只需要如上两步,当Activity页面生命周期发生变化时,都会通知到LifecycleObserverDemo。同样,本文以Activity为例,介绍Lifecycle感知生命周期的原理。

生命周期绑定实现原理

实现原理简介

通过在对指定activity注册无UI的Fragment,传递页面Activity生命周期到Fragment。然后通过Fragment绑定LifecycleRegistry,当Fragment的生命周期变化时,回调LifecycleRegistry中LifecycleObserver对象相应的生命周期回调方法。

如何传递生命周期

下图是文章Android Architecture Component -- Lifecycle 浅析中关于Lifecycle生命周期传递的一幅图,我觉得很清晰地展示了生命周期的传递过程。下面我们跟着这幅图,来一步步看一下生命周期是如何传递的。

生命周期传递到LifecycleObserver

  • 如何在Activity上注册无UI的ReportFragment

    首先看下LifecycleDispatcher初始化的过程:

    • 利用 ContentProvider 的特点在应用程序初始化时,向其注入两行代码:
    LifecycleDispatcher.init(getContext());
    ProcessLifecycleOwner.init(getContext());  // 监听整个应用前后台切换
    复制代码
    • 这个ContentProvider从哪里来?查看apk中的AndroidManifest.xml文件,发现多了一个ContentProvider声明:
    <provider
        android:name="android.arch.lifecycle.LifecycleRuntimeTrojanProvider"
        android:authorities="${applicationId}.lifecycle-trojan"
        android:exported="false"
        android:multiprocess="true" />
    复制代码

在这个LifecycleRuntimeTrojanProvider(低版本的AAC里,这个类叫ProcessLifecycleOwnerInitializer)的初始化方法中,实现了LifecycleDispatcher的相应初始化操作。

下面再来看一下LifecycleDispatcher的init方法:

static void init(Context context) {
    if (sInitialized.getAndSet(true)) {
        return;
    }
    ((Application) context.getApplicationContext())
            .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
}
复制代码

在 LifecycleDispatcher#init(Context) 中,它通过 registerActivityLifecycleCallbacks 方法,向当前的 Application 注册一个 DispatcherActivityCallback。但 Lifecycle 并没使用 ActivityLifecycleCallbacks 来监听并派发生命周期事件。而是通过一个无 UI 的 Fragment,在 DispatcherActivityCallback#onActivityCreated 可以看到它在 Activity#onCreate 时,为 Activity 添加一个 ReportFragment。最终由 ReportFragment 来监听各个生命周期事件,然后传递给 LifecycleRegistry。

  • 无UI的Fragment与LifecycleRegistry建立联系

查看ReportFragment的生命周期回调方法:

@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;
}
复制代码

回调生命周期方法时,会调用dispatch(Lifecycle.Event event)方法。看下dispatch(Lifecycle.Event event)方法的源码:

private void dispatch(Lifecycle.Event event) {
    Activity activity = getActivity();
    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);
        }
    }
}
复制代码

这里会通过ReportFragment注册的Activity的getLifecycle()方法获取LifecycleRegistry,然后调用LifecycleRegistry的handleLifecycleEvent(@NonNull Lifecycle.Event event)处理传递的生命周期Event。

  • _LifecycleAdapter如何与LifecycleRegistry建立联系

    在LifecycleRegistry中,定义了如下的map:

    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();
    复制代码

    当我们在页面Activity中将观察者加入集合时,加入的就是上面定义的mObserverMap。ObserverWithState对象构造函数初始化时,通过Lifecycling.getCallback(observer)方法返回GenericLifecycleObserver对象,实际上就是_LifecycleAdapter对象。因为_LifecycleAdapter实现了GenericLifecycleObserver。

    static GenericLifecycleObserver getCallback(Object object) {
        if (object instanceof FullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
        }
    
        if (object instanceof GenericLifecycleObserver) {
            return (GenericLifecycleObserver) object;
        }
    
        final Class<?> klass = object.getClass();
        int type = getObserverConstructorType(klass);
        if (type == GENERATED_CALLBACK) {
            List<Constructor<? extends GeneratedAdapter>> constructors =
                    sClassToAdapters.get(klass);
            if (constructors.size() == 1) {
                GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                        constructors.get(0), object);
                return new SingleGeneratedAdapterObserver(generatedAdapter);
            }
            GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
            for (int i = 0; i < constructors.size(); i++) {
                adapters[i] = createGeneratedAdapter(constructors.get(i), object);
            }
            return new CompositeGeneratedAdaptersObserver(adapters);
        }
        return new ReflectiveGenericLifecycleObserver(object);
    }
    复制代码

基于注解生成了_LifecycleAdapter 的class,通过反射生成_LifecycleAdapter对象

  • _LifecycleAdapter回调生命周期方法,继续传递生命周期给最终的观察者

LifecycleRegistry和_LifecycleAdapter建立联系后,生命周期会通过调用ObserverWithState的dispatchEvent方法:

void dispatchEvent(LifecycleOwner owner, Event event) {
    State newState = getStateAfter(event);
    mState = min(mState, newState);
    mLifecycleObserver.onStateChanged(owner, event);
    mState = newState;
}
复制代码

最终,会调用mLifecycleObserver,即我们前面返回的_LifecycleAdapter的onStateChanged方法。下面看下_LifecycleAdapter的实现:

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;
  }
}
复制代码

上面的类,可以在 build 目录下找到。这是注解处理器为我们生成了 LifecycleObserverDemo_LifecycleAdapter,不过这只是一个适配器,用于将生命周期事件派发到 LifecycleObserverDemo 对应的方法。至此,LifecycleObserverDemo实现了对页面Activity生命周期的感知。

核心类介绍

  • LifecycleObserver:接口,标记一个类是可观察的,基于注解实现相应回调方法
  • Lifecycle:抽象类,拥有android生命周期
  • LifecycleRegistry:继承Lifecycle,可以处理多LifecycleObserver
  • LifecycleOwner:接口,持有一个android lifecycle
  • LifecycleRegistryOwner:接口,继承LifecycleOwner,返回LifecycleRegistry
  • LifecycleDispatcher:在Application中hook,观察activity的生命周期并分发
  • LifecycleRuntimeTrojanProvider:LifecycleDispatcher等初始化

生命周期管理框架实践

Demo省略了注解相关步骤,需要观察者自己去实现一个ZRLifecycleObserver接口。虽然稍有不同,但是不妨碍理解。

Demo的框架图如下所示:

框架图

使用的话也比较简单,主要进行以下一些设置。

  • 观察者实现ZRLifecycleObserver接口
public class MyView extends View implements ZRLifecycleObserver {

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context,
            @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void onCreate() {
        System.out.println("MyView onCreate");
    }

    @Override
    public void onStart() {
        System.out.println("MyView onStart");
    }

    @Override
    public void onResume() {
        System.out.println("MyView onResume");
    }

    @Override
    public void onPause() {
        System.out.println("MyView onPause");
    }

    @Override
    public void onStop() {
        System.out.println("MyView onStop");
    }

    @Override
    public void onDestroy() {
        System.out.println("MyView onDestroy");
    }

    @Override
    public void onRestart() {
        System.out.println("MyView onRestart");
    }
}
复制代码
  • 应用启动时初始化ZRLifecycleDispatcher
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ZRLifecycleDispatcher.init(this);
    }
}
复制代码
  • 被观察页面实现ZRLifecycleRegistryOwner,并将要要观察此页面生命周期的观察者对象加入集合
public class MainActivity extends Activity implements ZRLifecycleRegistryOwner {

    private ZRLifecycleRegistry lifecycleRegistry = new ZRLifecycleRegistry(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyView myView = findViewById(R.id.view_test);

        getLifecycle().addObserver(myView);

    }

    @Override
    public ZRLifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}
复制代码

具体工程代码可以从这里获取:CustomAACLifecycleDemo

结束

至此,关于AAC如何绑定页面生命周期的原理讲解结束。在上一篇文章如何绑定页面生命周期(一)-Glide实现,介绍了Glide绑定生命周期的原理。两种绑定页面生命周期的方式,大家可以对比着看,相信肯定会对绑定页面生命周期有更加深入的了解。

参考

Android Architecture Component -- Lifecycle 浅析

关注下面的标签,发现更多相似文章
评论