Android 构建可管理生命周期的应用(一)

LifecycleOwner

LifecycleOwner 是一个接口,表示某个类拥有一个 Lifecycle。它的主要职责是提供对 Lifecycle 对象的访问。实现 LifecycleOwner 接口的类需要返回一个 Lifecycle 实例,该实例描述了其实现类的生命周期状态变化。

  • 常见的 LifecycleOwner 实现:

    • AppCompatActivity
    • Fragment

通过实现 LifecycleOwner,这些组件可以通知其他对象它们的生命周期事件(如 ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY),使得这些对象可以根据宿主组件的生命周期来调整自己的行为。

LifecycleRegistry

LifecycleRegistryLifecycle 类的一个具体实现,它提供了管理生命周期状态的方法。通常情况下,当你自定义一个实现了 LifecycleOwner 的类时,你会使用 LifecycleRegistry 来跟踪和报告生命周期状态的变化。

  • 用途:

    • 它允许你在自定义组件中精确地控制生命周期状态。
    • 可以用来创建具有生命周期感知能力的自定义视图或其他组件。

传统方式

传统方式一般是指 Java 语言,没有使用协程的情况下。

Fragment 中的使用

初始化生命周期相关逻辑
csharp 复制代码
public Fragment() {
    initLifecycle();
}

private void initLifecycle() {
    mLifecycleRegistry = new LifecycleRegistry(this);
    ...
}

LifecycleRegistry 是生命周期的实现者

Fragment 生命周期回调
scss 复制代码
//onCreate
void performCreate(Bundle savedInstanceState) {
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    ...
}
//onStart
void performStart() {
    ...
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    if (mView != null) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }
}
//onResume
void performResume() {
    ...
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    if (mView != null) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }
}
void performStop() {
    if (mView != null) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
    }
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}
void performDestroy() {
    mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
通过观察者生命周期变化

Fragment生命周期变化的时候,handleLifecycleEvent方法最后会通知所有的观察者

kotlin 复制代码
open fun handleLifecycleEvent(event: Event) {
    moveToState(event.targetState)
}
private fun moveToState(next: State) {
    ...
    sync()
    ...
}
//简单理解就是状态同步,生命周期同步变化,让观察者做出需要的改变
private fun sync() {
    ...
    while (!isSynced) {
        newEventOccurred = false
        if (state < observerMap.eldest()!!.value.state) {
            backwardPass(lifecycleOwner)
        }
        val newest = observerMap.newest()
        if (!newEventOccurred && newest != null && state > newest.value.state) {
            forwardPass(lifecycleOwner)
        }
    }
}

到这里我们已经简单介绍完了,当Fragment 生命周期变化的时候,如何通过 LifecycleOwnerLifecycleRegistry 通知观察者的

注册

通知观察者流程,但是应该还需要有一个注册流程,没有注册就拿不到观察者

前面讲过 LifecycleOwner 表示某个类拥有一个 Lifecycle ,而LifecycleRegistryLifecycle 的具体实现者。在 LifecycleRegistry 中,有一个注册方法,addObserver 主要是通过它来完成注册流程,当生命周期变化时候,就会把注册在LifecycleRegistry 中的所有观察者都通知一遍。后面我们会讲具体的使用场景。

存在两个生命周期的实现者

通过查看Fragment源代码可以看到,有两个关注生命周期的实现,mLifecycleRegistrymViewLifecycleOwner

  • fragment.lifecycle:表示 整个 Fragment 的生命周期
  • viewLifecycleOwner.lifecycle:表示 Fragment 中 View 的生命周期

两个 Lifecycle 的生命周期状态流程对比,区别主要在于 onCreateonDestroy 方法对于

viewLifecycleOwner 来说不回调

Fragment 方法 fragment.lifecycle 状态 viewLifecycleOwner.lifecycle 状态
onCreate() CREATED 不可用(View 尚未创建)
onCreateView() CREATED
onStart() STARTED STARTED
onResume() RESUMED RESUMED
onPause() STARTED STARTED
onStop() CREATED CREATED
onDestroyView() DESTROYED
onDestroy() DESTROYED 已经销毁

Activity 中的使用

Activity 中 ,一样是通过mLifecycleRegistry 来管理生命周期,也就是通过它把Activity 的生命周期,

应用到各个组件,比如ViewModel,让其他组件同样具备生命周期的能力

具备生命周期的组件

  • LiveData
arduino 复制代码
// 观察 LiveData
viewModel.username.observe(viewLifecycleOwner, Observer { username ->
    textView.text = "当前用户:$username"
})

在传统的方式,我们一般会这样使用 LiveData ,使用 viewLifecycleOwner

less 复制代码
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    ...
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ...
    owner.getLifecycle().addObserver(wrapper);
}

最后还是调用了 owner.getLifecycle(),也就是真实的实现者,LifecycleRegistry,向它注册了观察者。

在我们每次向 LiveData 赋予新值的时候,会通知观察者

typescript 复制代码
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    ...   
    if (!observer.mActive) {
        return;
    }
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    considerNotify(initiator);
    ...
}
private void considerNotify(ObserverWrapper observer) {
    ...
    observer.mObserver.onChanged((T) mData);
}

observer.mActive 表示它是具备生命周期的,只有活跃的情况下,才会发送消息。

scss 复制代码
@Override
boolean shouldBeActive() {
    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

也就是宿主,如果已经不活跃了,消息就不会发送了。

LifecycleBoundObserver onStateChanged方法内部,会主动解除绑定关系currentState == DESTROYED

less 复制代码
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
        Lifecycle.@NonNull Event event) {
    Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
    if (currentState == DESTROYED) {
        removeObserver(mObserver);
        return;
    }
    Lifecycle.State prevState = null;
    while (prevState != currentState) {
        prevState = currentState;
        activeStateChanged(shouldBeActive());
        currentState = mOwner.getLifecycle().getCurrentState();
    }
}
相关推荐
叽哥7 分钟前
Kotlin学习第 1 课:Kotlin 入门准备:搭建学习环境与认知基础
android·java·kotlin
风往哪边走25 分钟前
创建自定义语音录制View
android·前端
用户20187928316725 分钟前
事件分发之“官僚主义”?或“绕圈”的艺术
android
用户20187928316726 分钟前
Android事件分发为何喜欢“兜圈子”?不做个“敞亮人”!
android
Kapaseker2 小时前
你一定会喜欢的 Compose 形变动画
android
QuZhengRong3 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
zhangphil4 小时前
Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin(2)
android·kotlin
程序员码歌10 小时前
【零代码AI编程实战】AI灯塔导航-总结篇
android·前端·后端
书弋江山12 小时前
flutter 跨平台编码库 protobuf 工具使用
android·flutter
来来走走14 小时前
Flutter开发 webview_flutter的基本使用
android·flutter