一、一个 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 里抽出来,放到了不受系统生杀权影响的地方。