为什么 Android 不用接口做 Activity 通信?

一、一个 iOS 开发者,把我问住了

上周,一个刚从 iOS 转过来的同事问我:

"Android 为啥不喜欢用接口回调传结果? iOS 那边 delegate、closure 不就挺好吗?"

我第一反应是:

"因为 Activity 可能被销毁。"

但说完我自己都觉得不够到位。

这话没错,但只解释了"现象",没解释"为什么会这样"。

后来我们从 Activity 聊到 Binder,从生命周期聊到系统架构,他来了一句:

"原来这不是 API 习惯问题,这是系统底层设计不一样。"

对,就是这个点,这个和iOS设计不太一样。


二、你以为这是"用法问题",其实是"设计问题"

先把问题抽象一下:

为什么 Android Activity 通信不用接口,而用 onActivityResult

很多人会这么答:

  • Activity 可能被销毁
  • 防止内存泄漏

这些都对,但都停在"现象层"。

真正的问题是:

Android 整个系统,根本就不是为"对象引用通信"设计的。


三、接口通信,本质是"共享内存模型"

你写的这段代码,其实隐含了一个前提:

👉 这件事本质上是:

A 和 B 共享一块内存,并且持有同一个对象引用

这在单进程世界是成立的。

但问题来了


四、Android 是"消息驱动系统",不是"对象驱动系统"

Android 的三大通信基石:

  • Intent
  • Binder
  • Bundle

它们有一个共同点:

全部是"消息",不是"引用"

换句话说:

模型 特征
接口 callback 共享对象引用(共享内存)
Android 组件通信 发送消息(序列化数据)

这不是 Activity 的限制,这是整个系统的选择。


五、第一个致命约束:组件不归你管

在 Android 里,Activity 的生杀大权在系统手里(ActivityManagerService)。

这意味着什么?

👉 A 活着,不是你说了算

经典场景:

css 复制代码
A → 打开 B
↓
用户接电话 / 切后台
↓
系统内存紧张 → 杀掉 A(B 还活着)
↓
用户回到 B,点击完成

如果你用接口:

css 复制代码
B → callback.onResult()
        ↓
💥 A 已经没了

问题不是"可能 crash",而是:

这个调用在语义上已经失效了


六、所以 Android 只能选择一条路

既然:

  • 不能依赖对象还活着
  • 不能传递对象引用

那就只剩一个解法:

只传递"可序列化的数据",由系统负责中转

这就是 onActivityResult 的本质。


七、你以为它是 callback,其实它是"系统协议"

来看真实模型:

css 复制代码
A 调用 startActivityForResult
        ↓
系统记录(Token + requestCode)
        ↓
B 执行(A 可以随时被杀)
        ↓
B setResult + finish
        ↓
系统查记录
        ↓
如果 A 不在 → 重建 A
        ↓
分发结果(onActivityResult)

注意三个关键点:

1️⃣ 不存对象,只存"标识"

系统只认 Token,不认引用。


2️⃣ 回调的不是对象,是"生命周期事件"

onActivityResult 本质是一次系统分发事件 👉 不是函数回调


3️⃣ 整个过程是"无状态设计"

requestCode 的意义是:

在没有上下文的情况下,恢复语义


八、iOS 为什么可以用接口?

因为它解决的是另一个问题。

在 iOS 里,ViewController 由导航栈管理:

css 复制代码
UINavigationController
    └── [A, B]

这意味着:

只要 B 还在,A 一定还在

所以:

swift 复制代码
delegate?.onResult()

是安全的。


九、但 iOS 一旦跨进程,也"变成 Android"

举两个例子:

  • 相机(UIImagePickerController)
  • 分享(UIActivityViewController)

👉 这些场景:

  • 不再使用 delegate 持有引用
  • 而是使用系统回调 / completion

本质上:

一旦跨进程,iOS 也必须放弃对象引用模型


十、本质差异,不在 API,在"控制权"

Android iOS
生命周期控制 系统(不可控) 导航栈(可控)
通信模型 消息驱动 引用驱动(单进程)
跨进程能力 默认支持 需要系统桥接
回调本质 生命周期分发 对象调用

十一、现代 API 只是"糖"

现在我们用:

kotlin 复制代码
registerForActivityResult { }

看起来像 callback。

但本质上:

底层还是 requestCode + 系统分发

它做的只是:

  • 生命周期绑定
  • 类型安全
  • API 收敛

👉 这是"体验优化",不是"模型改变"。


十二、总结

Android 不用接口通信,不是因为 Activity 会被销毁,而是因为整个系统是"消息驱动 + 跨进程优先"的架构,天然不支持对象引用语义。(笔者认为这个设计初衷是好的,但是过重了,尤其对于应用内的通信)

  • 生命周期不可靠 → 不能依赖对象存在
  • 跨进程 → 引用无法传递
  • 系统调度 → 回调必须可恢复
  • 理解了这一点,你就知道为什么应用内ViewModel + Flow 是正确答案------它把"状态"从 Activity 里抽出来,放到了不受系统生杀权影响的地方。
相关推荐
恋猫de小郭1 小时前
2026 Android I/O ,全新 AI 手机、 Android PC 和车载驾驶
android·前端·flutter
赏金术士14 小时前
Kotlin ViewModel
android·kotlin
vistaup15 小时前
kotlin 二维码实现高斯模糊
android·kotlin
愈努力俞幸运16 小时前
function calling与mcp
android·数据库·redis
阿巴斯甜17 小时前
LeakCanary
android
阿巴斯甜17 小时前
compose
android
阿巴斯甜17 小时前
Glide
android
-SOLO-17 小时前
使用Perfetto debug trace查看超时slice
android
阿巴斯甜17 小时前
Retrofit
android