博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何绑定页面生命周期(二)-基于Android Architecture Components的Lifecycle实现
阅读量:6877 次
发布时间:2019-06-26

本文共 9791 字,大约阅读时间需要 32 分钟。

上篇文章介绍了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对象相应的生命周期回调方法。

如何传递生命周期

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

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

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

    • 利用 ContentProvider 的特点在应用程序初始化时,向其注入两行代码:
    LifecycleDispatcher.init(getContext());ProcessLifecycleOwner.init(getContext());  // 监听整个应用前后台切换复制代码
    • 这个ContentProvider从哪里来?查看apk中的AndroidManifest.xml文件,发现多了一个ContentProvider声明:
    复制代码

在这个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的生命周期回调方法:

@Overridepublic void onActivityCreated(Bundle savedInstanceState) {    super.onActivityCreated(savedInstanceState);    dispatchCreate(mProcessListener);    dispatch(Lifecycle.Event.ON_CREATE);}@Overridepublic void onStart() {    super.onStart();    dispatchStart(mProcessListener);    dispatch(Lifecycle.Event.ON_START);}@Overridepublic void onResume() {    super.onResume();    dispatchResume(mProcessListener);    dispatch(Lifecycle.Event.ON_RESUME);}@Overridepublic void onPause() {    super.onPause();    dispatch(Lifecycle.Event.ON_PAUSE);}@Overridepublic void onStop() {    super.onStop();    dispatch(Lifecycle.Event.ON_STOP);}@Overridepublic 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
    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
    > 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;    }}复制代码

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

结束

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

参考

转载地址:http://dfgfl.baihongyu.com/

你可能感兴趣的文章
python3爬虫(二)实战- 爬糗事百科
查看>>
windowsXP用户被禁用导致不能网站登录
查看>>
第 8 章 TokyoCabinet/Tyrant
查看>>
PowerShell中进行文件读取,信息排序,分类计数。
查看>>
JAVA 之 继承
查看>>
使用fiddler模拟http请求
查看>>
利用caffe生成 lmdb 格式的文件,并对网络进行FineTuning
查看>>
一看就懂的ReactJs入门教程-精华版
查看>>
阿里巴巴1682亿背后的“企业级”高效持续交付
查看>>
(转) ICML2016 TUTORIAL参会分享
查看>>
如何实现跨 Docker 主机存储?- 每天5分钟玩转 Docker 容器技术(73)
查看>>
迁移式升级的测试
查看>>
美国大规模“断网”暴露哪些问题
查看>>
苹果旗下为何没有独立风投部门 一切为了保密
查看>>
缩小信息技术部门与业务部门间的脱节 国外CIO是这样做的
查看>>
37.5亿美元估值 终端安全厂商Tanium再融资1亿美元
查看>>
标杆电价下调致光伏产业难别寒冬 高效组件仍稀缺
查看>>
“光伏领跑者”不能违背提高技术门槛的初衷
查看>>
贵州发布大数据十项工程
查看>>
“五个一百”铸成网络正能量新“支点”
查看>>