Android 架构演进:从生命周期事件到结构化任务

Android 生命周期,是每一个 Android 开发者都绕不开的痛。

早期我们习惯在:

kotlin 复制代码
onStart()
onStop()
onResume()
onPause()

里面处理各种业务。

后来有了 LifecycleObserver,再到 Kotlin 协程、Flow 成为现代 Android 异步编程的重要组成部分。

如果只是从 API 的变化来看,很容易得到:

text 复制代码
Lifecycle 回调
        ↓
LifecycleObserver
        ↓
Coroutine / Flow

但真正值得关注的,并不仅仅是 API 的变化。

而是背后的编程模型发生了变化:

Android 生命周期管理,正在从"生命周期事件驱动",演进到"生命周期约束下的结构化任务"。


一、最初:生命周期事件驱动

最早 Android 的生命周期模型非常简单。

Activity 提供:

kotlin 复制代码
onCreate()
onStart()
onResume()
onPause()
onStop()
onDestroy()

开发者根据生命周期回调执行对应逻辑。

例如:

kotlin 复制代码
override fun onStart() {
    super.onStart()
    startNetworkMonitor()
}


override fun onStop() {
    stopNetworkMonitor()
    super.onStop()
}

它的关系:

text 复制代码
Lifecycle

    ↓

生命周期事件

    ↓

回调方法

    ↓

开发者执行逻辑

生命周期本身并不知道:

  • 你启动了什么任务
  • 任务什么时候结束
  • 是否需要取消
  • 资源什么时候释放

它只是告诉你:

"我现在发生了什么。"

这就是典型的事件驱动模型。


二、LifecycleObserver:把生命周期事件独立出来

随着业务复杂,直接把大量逻辑写在 Activity 中会越来越臃肿。

于是 AndroidX 引入了 Lifecycle。

生命周期逻辑可以独立:

kotlin 复制代码
class NetworkObserver : DefaultLifecycleObserver {
    override fun onStart(owner: LifecycleOwner) {
        startNetworkMonitor()
    }

    override fun onStop(owner: LifecycleOwner) {
        stopNetworkMonitor()

    }
}

架构变成:

text 复制代码
LifecycleOwner

      ↓

Lifecycle

      ↓

LifecycleObserver

      ↓

onStart / onStop

相比以前:

text 复制代码
Activity
    |
    |
大量生命周期代码

现在:

text 复制代码
Activity

    ↓

LifecycleObserver

    ↓

业务逻辑

代码职责更加清晰。

但是:

LifecycleObserver 只是解决了代码组织问题,并没有改变事件驱动模型。

底层依然是:

text 复制代码
生命周期变化

        ↓

事件通知

        ↓

调用回调

        ↓

执行逻辑

生命周期依然只是:

"告诉开发者发生了什么。"


三、传统 LifecycleObserver 模型:生命周期和数据传递是分开的

来看一个真实场景:

监听网络状态。

传统方式:

kotlin 复制代码
class NetworkObserver(
    context: Context,
    private val onStatusChanged: (Boolean) -> Unit

) : DefaultLifecycleObserver {

    private val connectivityManager =
        context.getSystemService(
            Context.CONNECTIVITY_SERVICE
        ) as ConnectivityManager

    private val networkCallback =
        object : ConnectivityManager.NetworkCallback() {

            override fun onAvailable(network: Network) {
                onStatusChanged(true)
            }

            override fun onLost(network: Network) {
                onStatusChanged(false)
            }
        }
}

Activity 使用:

kotlin 复制代码
class MainActivity : AppCompatActivity() {

    private val observer =
        NetworkObserver(this) { connected ->

            if (connected) {
                showOnline()

            } else {
                showOffline()
            }
        }


    override fun onCreate(
        savedInstanceState: Bundle?
    ) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(observer)

    }
}

看起来很自然。

但是分析整个链路:

text 复制代码
LifecycleObserver

        |

        | 管理生命周期

        ↓

ConnectivityManager.NetworkCallback

        |

        | 产生数据

        ↓

onStatusChanged(Boolean)

        |

        | 回调通知

        ↓

Activity 更新 UI

这里其实存在两个完全不同的问题:

1. 生命周期管理

负责:

text 复制代码
什么时候注册监听

什么时候取消监听

例如:

text 复制代码
onStart()

onStop()

2. 数据传递

负责:

text 复制代码
网络变化

↓

Boolean

↓

UI 更新

通过:

kotlin 复制代码
onStatusChanged()

完成。


问题在于:

生命周期和数据流之间没有统一模型。

开发者需要自己维护:

text 复制代码
生命周期

    +

监听任务

    +

回调关系

    +

资源释放

四、传统回调模型的问题

当业务简单时:

text 复制代码
NetworkObserver
        ↓
Activity

没有问题。

但是现代 App 往往存在:

text 复制代码
网络状态

蓝牙状态

GPS状态

数据库变化

文件上传进度

WebSocket消息

于是代码逐渐变成:

text 复制代码
NetworkObserver

      ↓

callback

      ↓

Activity



BluetoothObserver

      ↓

callback

      ↓

Activity



LocationObserver

      ↓

callback

      ↓

Activity

最终 Activity 里面充满:

kotlin 复制代码
observer.setCallback {

}


observer.setCallback {

}


observer.setCallback {

}

开发者需要人工维护:

  • 谁注册
  • 谁取消
  • 谁还活着
  • 谁应该接收数据
  • 页面销毁后是否还有回调

生命周期只负责:

text 复制代码
开始

结束

但是任务和数据:

text 复制代码
怎么启动

怎么取消

怎么传递

怎么释放

都需要自己管理。


五、协程:异步任务开始拥有自己的生命周期

现代 Android 最大变化来自 Kotlin 协程。

例如:

kotlin 复制代码
lifecycleScope.launch {
    loadData()
}

这里创建的不只是一个异步调用。

而是:

text 复制代码
CoroutineScope

        ↓

Job

        ↓

Task

这个 Job 拥有自己的生命周期。

例如:

text 复制代码
Activity

   ↓

Lifecycle

   ↓

CoroutineScope

   ↓

Job

   ↓

Network Request

当 Activity 销毁:

text 复制代码
Lifecycle Destroy

        ↓

CoroutineScope cancel

        ↓

Job cancel

        ↓

任务结束

最大的变化:

异步任务第一次拥有了结构化的生命周期。


六、从事件通知,到任务边界

这是整个演进过程中最重要的变化。

传统:

text 复制代码
Lifecycle

    ↓

START事件

    ↓

onStart()

    ↓

手动启动任务

现代:

text 复制代码
Lifecycle

    ↓

Coroutine Scope

    ↓

Job

    ↓

Task

生命周期不再只是告诉你:

"发生了什么。"

而开始决定:

"这个任务是否应该存在。"


七、结构化并发:任务形成层级关系

协程进一步带来了结构化并发。

例如:

kotlin 复制代码
lifecycleScope.launch {

    launch {
        loadUser()
    }

    launch {

        loadMessage()

    }

    launch {
        loadNotification()
    }

}

任务关系:

text 复制代码
             Parent Job

                 |

     ┌───────────┼───────────┐

     ↓           ↓           ↓

 User Job   Message Job  Notification Job

父任务取消:

text 复制代码
Parent Job

      ↓

Cancel

      ↓

Child Jobs

      ↓

全部取消

这和传统生命周期代码最大的区别:

以前:

text 复制代码
开发者维护任务关系

现在:

text 复制代码
结构表达任务关系

八、Flow:持续数据也进入生命周期模型

协程解决了任务生命周期。

但是现代应用还有大量持续数据:

例如:

text 复制代码
网络在线

    ↓

网络离线

    ↓

重新在线

这种场景更适合:

kotlin 复制代码
Flow<Boolean>

Flow 表达:

一个持续产生数据的数据源。

例如:

kotlin 复制代码
fun observeNetwork(): Flow<Boolean> =

    callbackFlow {
        val callback =
            object : ConnectivityManager.NetworkCallback() {

                override fun onAvailable(network: Network) 
                    trySend(true)
                }

                override fun onLost(network: Network) {
                    trySend(false)
                }
            }

        connectivityManager.registerNetworkCallback(
            request,
            callback
        )

        awaitClose {
            connectivityManager.unregisterNetworkCallback(
                callback
            )

        }

    }

此时模型变化:

以前:

text 复制代码
NetworkCallback

        ↓

callback(Boolean)

        ↓

Activity

现在:

text 复制代码
NetworkCallback

        ↓

Flow

        ↓

Coroutine

        ↓

UI

数据成为独立的数据流。


九、生命周期开始约束 Flow 和任务

现代 Android:

kotlin 复制代码
repeatOnLifecycle(
    Lifecycle.State.STARTED
) {

    networkFlow.collect {
        render(it)
    }

}

这里生命周期的角色已经变化。

以前:

text 复制代码
Lifecycle

告诉我:

onStart

onStop

现在:

text 复制代码
Lifecycle

决定:

任务什么时候应该存在

当页面不可见:

text 复制代码
Lifecycle

        ↓

Coroutine Cancel

        ↓

Flow停止收集

        ↓

awaitClose释放资源

完整链路:

text 复制代码
Lifecycle

      ↓

Coroutine Scope

      ↓

Job

      ↓

Flow

      ↓

Data Source

      ↓

Resource Release

形成闭环。


十、两种模型真正的区别

回头看:

传统模型

text 复制代码
Lifecycle

      ↓

Event

      ↓

Observer

      ↓

Callback

      ↓

开发者管理任务

关注:

发生了什么?


现代模型

text 复制代码
Lifecycle

      ↓

State

      ↓

Coroutine Scope

      ↓

Structured Concurrency

      ↓

Flow

      ↓

Cancellation

关注:

当前生命周期下,哪些任务应该存在?


十一、生命周期角色的变化

因此 Android 生命周期的价值已经发生变化。

过去:

生命周期是事件通知器。

现在:

生命周期是异步任务的边界管理者。

可以简单总结:

第一阶段:事件驱动

text 复制代码
Lifecycle

    ↓

Event

    ↓

Callback

关注:

发生了什么。


第二阶段:生命周期观察

text 复制代码
Lifecycle

    ↓

Observer

    ↓

onStart/onStop

关注:

生命周期变化时我要做什么。


第三阶段:生命周期约束下的结构化任务

text 复制代码
Lifecycle

    ↓

State

    ↓

Coroutine

    ↓

Job

    ↓

Flow

    ↓

Cancellation

关注:

当前状态下任务应该存在多久。


十二、总结

Android 生命周期的演进,表面看是 API 的变化。

但本质是异步编程模型的变化。

过去:

text 复制代码
Lifecycle

    ↓

事件

    ↓

Callback

    ↓

手动管理任务

现在:

text 复制代码
Lifecycle

    ↓

状态约束

    ↓

Coroutine Scope

    ↓

Structured Concurrency

    ↓

Flow

    ↓

Cancellation

所以可以概括:

以前,生命周期告诉你"发生了什么";现在,生命周期开始决定"任务能存在多久"。

最终:

text 复制代码
Lifecycle       → 管边界

Coroutine       → 管任务

Flow            → 管数据

Cancellation    → 管结束

真正的变化,不是少写了几个:

kotlin 复制代码
onStart()
onStop()

而是:

Android 从"开发者监听生命周期事件并手动拼装异步逻辑",演进到"利用生命周期约束结构化管理任务、数据和资源"。

LifeCycleSample

相关推荐
一笑的小酒馆8 小时前
AndroidKMP之网络请求
android
aqi0012 小时前
鸿蒙版本的JSBridge兼容与安卓配套的H5啦
android·华为·harmonyos·鸿蒙·移动应用
事圆则缓12 小时前
MVVM 的理解与设计
android·android jetpack
码农阿豪13 小时前
我把 OpenClaw 装进旧安卓手机后,又折腾了 3 天:飞书、ADB、SSH 全部打通
android·智能手机·飞书
有什么事15 小时前
把安卓搬上云端:云手机系统改造与内核优化拆解
android·智能手机
方白羽15 小时前
性能分析:Android Studio Profiler
android·性能优化·app
没文化的阿浩15 小时前
【MySQL】用户管理
android·mysql·adb
FlightYe17 小时前
音视频修炼之基础理论(五):AAC格式与解析
android·linux·c++·音视频·aac
法欧特斯卡雷特17 小时前
Kotlin 2.4.20 现已发布,新特性多不多?
android·开源·全栈