Android Jetpack Components of Lifecycle 学习笔记

Android Jetpack Components of LiveData 学习笔记

Android Jetpack Components of ViewModel 学习笔记

 

都说天下文章一大抄。不过我不担心,我从来不抄袭别人的见解。

也有人说博客、GibHub 上 90% 的内容都是重复的。这句话我赞同,但我不觉得这是件坏事。同一个事物,没有个人都应该有自己的辩证理解,否则就真的成为了天下文章一大抄了。

为了阐明我自己的理解、为了当做笔记便于日后回顾、也为了方便后来者少走弯路,我还是鼓起勇气写下后续的文章。尽管有那么多大神发布过类似的优秀文章。

说了一堆废话,今天我要聊的是 Lifecycle 组件。

组件地址:https://developer.android.google.cn/topic/libraries/architecture/lifecycle

你也可参考这位大佬的系列文章:https://www.jianshu.com/p/b1208012b268

插句废话:

访问 Android 官方网站 https://developer.android.com  需要的,否则无法访问;

访问 Android 中文网站 https://developer.android.google.cn 不需要。

貌似内容与 .com 网站一样,.google.cn 官方会定期更新的。

Lifecycle 环境配置:

1、如果是 sdk 小于 26 的版本,需要导入依赖包 android.arch.lifecycle

2、如果是 androidx 的环境,也需要导入依赖包,可参考 https://developer.android.google.cn/jetpack/androidx/releases/lifecycle#declaring_dependencies

3、除去以上情况之外,不需要任何导入,从 sdk 26 开始,系统内置了 Lifecycle 依赖包。

 

Lifecycle 官方原文定义:

Lifecycle-aware components perform actions in response to a change in the lifecycle status of another component, such as activities and fragments. These components help you produce better-organized, and often lighter-weight code, that is easier to maintain.

看过官方的解释,也看过很多优秀的博客,都说 Lifecycle 是可感知 Activity 和 Fragment 生命周期的组件。

来一个 Demo 对比说明问题,比喻一个工具类的注册于反注册,传统写法如下:

public class TestBus {    private Activity mActivity;    public void registerBusEvent(Activity activity) {        this.mActivity = activity;        // TODO: 2019/8/11 if    }    public void unRegister(Activity activity) {        // TODO: 2019/8/11 if    }}
public class LifecycleActivity extends AppCompatActivity {    private TestBus mTestBus;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_lifecycle);        mTestBus = new TestBus();        mTestBus.registerBusEvent(this);    }    @Override    protected void onDestroy() {        super.onDestroy();        if (mTestBus != null) {            mTestBus.unRegister(this);        }    }}

总结官方的解释和各路大神的见解,得出以上代码有如下缺点:

1、万一 mTestBus 对象忘记在 Activity 的 onDestroy() 方法中反注册了,会不会悲剧?

2、如果有更多的类似的功能类,都在 Activity 的 onDestroy() 方法中反注册,无效的代码量增大,是不是也是悲剧?

3、Activity 本是系统进程与应用程序进程之间进行生命周期回调的代理类,不应该写入过多的业务代码。

 

为了解决上面的问题,于是就有了 Lifecycle 组件,可感知 Activity 和 Fragment 的生命周期,类似反注册的代码可以完全放在自己的业务内处理。先上完整的 Demo,再说细节吧:

public class TestBus implements LifecycleObserver {    private Activity mActivity;    public void registerBusEvent(Activity activity) {        this.mActivity = activity;        // TODO: 2019/8/11 if    }    private void unRegister(Activity activity) {        // TODO: 2019/8/11 if    }    // 需要监控 Activity onDestroy    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)    public void onDestroy() {        unRegister(mActivity);    }}
public class LifecycleActivity extends AppCompatActivity {    private TestBus mTestBus;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_lifecycle);        mTestBus = new TestBus();        mTestBus.registerBusEvent(this);        // 注册 lifecycle 观察者        getLifecycle().addObserver(mTestBus);    }//    @Override//    protected void onDestroy() {//        super.onDestroy();//        if (mTestBus != null) {//            mTestBus.unRegister(this);//        }//    }}

 

看完上面的代码后,你会发现 Activity 中明显的变化就是注释了 onDestroy() 方法。那么问题来了,不在 Activity 的 onDestroy() 方法中调用 TestBus 的反注册方法,TestBus 是怎么知道的?是不是 Lifecycle 把 Activity 做成事件源被观察者,然后让 TestBus 作为观察者,观察 Activity 的生命周期?那就来小撸一把源码吧。

 

首先看上面 Demo 中 Activity 的 onCreate() 方法中的那样代码,感觉像是注册观察者啊:

getLifecycle().addObserver(mTestBus);

你会发现 `getLifecycle()` 最终返回的是 `SupportActivity` 中的 `mLifecycleRegistry` 对象。

再深入分析 `LifecycleRegistry` 会发现,`Lifecycle` 是一个抽象类,里面提供了几个抽象方法,和两个枚举类。同时 `LifecycleRegistry` 继承了 `Lifecycle` 抽象类。

在`LifecycleRegistry` 的构造函数中,发现需要传入 `LifecycleOwner` 接口的实例,刚巧 `SupportActivity` 实现了此接口。

同时 `SupportActivity` 实现了接口的抽象方法 `getLifecycle()` ,返回的类型是必须是 `Lifecycle` 类型的。刚巧 `SupportActivity` 的 `getLifecycle()` 方法返回的是 `LifecycleRegistry` 类型。

我们继续分析代码 `getLifecycle().addObserver(mTestBus);` 像是往 `mLifecycleRegistry` 对象中添加观察者对象,需要的参数类型必须是 `LifecycleObserver`。这么巧,Demo 中的 `TestBus` 实现了接口 `LifecycleObserver`。

经过小段分析,我们理解为:

1、`SupportActivity` 内置了 `LifecycleRegistry` 对象,在构造 `LifecycleRegistry` 对象时,传入了自己的内存引用。

2、`LifecycleRegistry` 是 Activity 事件源的生命周期状态的管理类,在 `Activity` 初始化时创建。

3、`getLifecycle().addObserver(mTestBus);` 这行代码是注册观察者对象,当事件源生命周期变化时,会通知观察者。

到此,我们理解 `Lifecycle` 大部分原理,还剩下上例中 `TestBus` 中的几个注解的作用,和事件源的生命周期如何触发到 `TestBus` 的注解方法上的。

搜索 `Lifecycle.State` 枚举类,发现在 `LifecycleDispatcher.makeState()` 方法中使用到了。再在 `LifecycleDispatcher` 中继续追查 `Lifecycle.State` 的具体枚举,会发现在 `LifecycleDispatcher.onActivitySaveInstanceState()` 方法中用到了,同时在 `LifecycleDispatcher.DestructionReportFragment` 内部类中也大量使用到了。由此推测得出结论,当 `Activity` 和 `Fragment` 的生命周期发生变化时,会主动触发事件状态,最终都会调用到 `LifecycleRegistry.makeToState()` 方法中,再循环通知所有观察者对象的对应的方法中。

了解了上面的事件通知过程,那还有一步不知道。每当事件触发时,LifecycleRegistry 怎么知道观察者的哪个方法需要回调呢?

或者说上例中 TestBus 的 onDestroy() 方法如何被 LifecycleRegistry 回调呢?

我们观察注册观察者方法:

LifecycleRegistry.java@Overridepublic void addObserver(@NonNull LifecycleObserver observer) {    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;    // 注意看 ObserverWithState 的构造函数    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);        // ...}
ObserverWithState.javaObserverWithState(LifecycleObserver observer, State initialState) {    // 注意看 Lifecycling.getCallback() 方法    mLifecycleObserver = Lifecycling.getCallback(observer);    mState = initialState;}
Lifecycling.java@NonNullstatic 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);    // ...}
Lifecycling.javaprivate static int getObserverConstructorType(Class<?> klass) {    if (sCallbackCache.containsKey(klass)) {        return sCallbackCache.get(klass);    }    // 注意看这个方法    int type = resolveObserverCallbackType(klass);    sCallbackCache.put(klass, type);    return type;}
Lifecycling.javaprivate static int resolveObserverCallbackType(Class<?> klass) {    // anonymous class bug:35073837        // 此行代码    boolean hasLifecycleMethods = ClassesInfoCache.sInstance.hasLifecycleMethods(klass);        }
ClassesInfoCache.javaboolean hasLifecycleMethods(Class klass) {    if (mHasLifecycleMethods.containsKey(klass)) {        return mHasLifecycleMethods.get(klass);    }    Method[] methods = getDeclaredMethods(klass);    for (Method method : methods) {        OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);        if (annotation != null) {            // Optimization for reflection, we know that this method is called            // when there is no generated adapter. But there are methods with @OnLifecycleEvent            // so we know that will use ReflectiveGenericLifecycleObserver,            // so we createInfo in advance.            // CreateInfo always initialize mHasLifecycleMethods for a class, so we don't do it            // here.            createInfo(klass, methods);            return true;        }    }    mHasLifecycleMethods.put(klass, false);    return false;}

代码追查到这里,不想多说什么了。注解、反射!

源码分析到这里,已经很明了了。

Demo 地址:https://github.com/mengzhinan/Lifecycle_LiveData_ViewModel_demo

 

 

 

 

更多相关文章

  1. [置顶] Android SDK中的例子的源代码
  2. Android方法数超出限定的问题(multiDex,jumboMode)
  3. Android原生方法和Web JS互相调用-两种写法
  4. Android里的观察者模式应用
  5. android 访问网络不能在主线程中进行以及在线程中操作UI的解决方
  6. Android Studio——Android Studio更新升级方法
  7. SpannableString的使用方法
  8. Android文本输入框EditText属性和方法说明

随机推荐

  1. Android(安卓)学习笔记【基础扫盲篇】
  2. Android之网络请求2————OkHttp的基本
  3. android创建隐藏文件或者文件夹,并对其读
  4. 开发android,我们需要哪些技能基础
  5. Android应用程序四大组件
  6. 高通平台android 环境配置编译及开发经验
  7. Android(安卓)项目开发填坑记 - 使用 Mul
  8. Android(安卓)Studio 及日常常用命令
  9. androidx升级注意事项
  10. Android(安卓)ListView 滑动背景为黑色的