为什么 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 里抽出来,放到了不受系统生杀权影响的地方。
相关推荐
程序员陆业聪8 小时前
绕过Frida/Xposed的最后防线:SVC直接系统调用与Native反Hook实战
android
程序员陆业聪8 小时前
WebView与原生JS交互:JSBridge生产级实现与安全防护
android
我命由我1234511 小时前
Android 开发问题:MlKitException: An internal error occurred during initialization.
android·java·java-ee·android jetpack·android-studio·androidx·android runtime
Meteors.12 小时前
Android自定义 View 三核心方法详解
android
2501_9160074712 小时前
前端开发常用软件与工具全面指南
android·ios·小程序·https·uni-app·iphone·webview
赏金术士12 小时前
Android Tinker 热修复集成与使用指南 1.9.15.2
android·热修复·tinker
2603_9541383914 小时前
安卓误删文件先别慌!5个实用小技巧指南教你补救
android·智能手机
波诺波15 小时前
5-SOFA可变形的3D物体 5-elasticity.scn
android
2501_9159090616 小时前
iOS应用性能优化:十大策略提升用户体验与开发效率
android·ios·小程序·https·uni-app·iphone·webview
sun00770017 小时前
打通android全链路,网卡驱动, 内核 , 到上层hal, framework
android