想象你住在一个语言不通的“异世界小区”里。小区里所有居民都说同一种方言——Dart,生活便利。可一旦你想查询手机电量、调用摄像头、读取 GPS 定位,就不得不跟“小区外”的原生世界打交道。外面的人说的是完全不同的方言:苹果园的人讲 Swift/Objective-C,安卓园的人讲 Kotlin/Java。语言不通怎么办?物业在你的房间里装了一台智能对讲机——这就是 Platform Channel。 这台对讲机有三种用法:打电话式的 MethodChannel,拨过去说“帮我查下电量”,对面查完再打回来告诉你结果;订阅广播式的 EventChannel,你订了某个频道,物业就持续把传感器数据推送到你耳边;互发短信式的 BasicMessageChannel,想聊什么就聊什么,随时发、随时回。本文会带你拆开这台对讲机,看懂它如何编解码、如何跨线程运转、如何自己装分机,以及怎样让通话又快又稳。
理解 Platform Channel 是 Flutter 开发者打开原生能力之门的钥匙。掌握它,你才能游刃有余地开发自定义插件、调用系统 API 与硬件能力,为团队打通 Dart 与原生世界的最后一公里。
目录
可视化演示
展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。
本节配有交互动效(进入视口后自动加载,约 3KB)。
系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T
通道总览——对讲机的三条线路
物业在你房间装了一台对讲机,面板上有三颗不同颜色的按键。第一颗蓝色按键“打电话”(Method),第二颗红色按键“订阅广播”(Event),第三颗绿色按键“互发短信”(Basic)。三种方式都接在同一条总线上,但沟通习惯完全不同。
这套对讲机系统在 Flutter 世界里的正式名字叫 Platform Channel。它分为三层:Dart 端的通道对象、原生端的通道对象,以及中间负责搬运消息的二进制管道。两端的对象靠一个唯一的名字“配对”——就像对讲机要调到同一个频道,说话才能被听见。
Flutter 官方提供三种通道。MethodChannel 以“方法名 + 参数”发起调用,返回一个 Future 结果,适合“一问一答”的场景,比如查询电量、读取联系人。EventChannel 让 Dart 端订阅一个事件流,原生端通过 EventSink 持续推送数据,适合传感器、定位、充电状态等实时数据。BasicMessageChannel 两端都可以主动发消息、异步回消息,适合需要持续双向对话的场景。三者的底层都是同一条消息发送管线,区别在于上层的会话模式。
所以,下次看到这三颗按键,别按错了——查一次性的东西按蓝色键,听持续的消息按红色键,两边要聊天就按绿色键。
- Platform Channel 总称指 Flutter 与原生通信机制的统称,就像“对讲机系统”这个总称。
- MethodChannel 元素表示“打电话”式的一次性请求-响应通道。
- EventChannel 元素表示“订阅广播”式的持续单向下行推送通道。
- BasicMessageChannel 元素表示“互发短信”式的持续双向消息通道。
- 集合并交三种通道共同组成完整的 Platform Channel 体系,缺一不可、互为补充。
通信原理——对讲机的翻译机
对讲机喊话时,声音不是直接飞到对面的。话筒先把语音变成电信号,听筒再把电信号还原成语音。中间这段“翻译”环节,决定了你说的话对面能不能听懂。
Platform Channel 的底层也有这样一台“翻译机”,名字叫 StandardMessageCodec。它在 Dart 端把对象编码成二进制字节流,通过通道的二进制管道运到原生端,再由原生端解码成对应的 Kotlin/Swift 对象。反过来推送时,执行逆过程。整个过程对上层透明,你感知不到字节的流动,就像打电话时不会意识到语音变成了电信号。
StandardMessageCodec 支持 null、bool、int、double、String、Uint8List、Int32List、Int64List、Float32List、Float64List、List 和 Map 这些类型。它会在每个值前面打上“类型标签”,就像快递包裹上贴的品类标签。超出这些基础类型的自定义对象,必须由开发者自己手动序列化成 Map 或二进制再传。如果双方对类型的理解不一致,就会抛出编解码异常(PlatformException),相当于翻译机听到了一个“字典里查不到的生词”。
理解这台翻译机,你就明白为什么自定义对象不能直接传——因为没有“普通话”翻译方案,必须自己写好“翻译词典”(手动序列化)。
- Dart 端对象Dart 世界里的值,如字符串 "hello"。
- 编码为字节把对象序列化成二进制字节流。
- 二进制字节通道上实际传输的二进制数据,即“翻译后的电信号”。
- 解码为原生值原生端把字节流还原成 Kotlin/Swift 对象。
- 原生端对象原生世界里最终拿到的值。
MethodChannel——打电话叫服务
早晨你拿起对讲机,按下蓝色通话键:“喂,物业吗?帮我看一下小区外面在下雨吗?”物业跑到门口看了一眼,回来告诉你:“在下的。”整个过程一问一答。你不需要站在对讲机前干等,挂了电话该干嘛干嘛,等结果到了自然有人按铃通知你。
MethodChannel 就是这种“打电话叫服务”的模式。Dart 端通过 invokeMethod('方法名', 参数) 发起调用,原生端注册对应的 handler 处理,处理完把结果放进 Result 回调返回给 Dart。Dart 端的返回值是一个 Future,可以用 async/await 等待,期间 UI 完全不受阻塞——就像你边等物业回电话边做自己的事。
在原生端(以 Android 为例),需要创建一个 MethodChannel 并实现 setMethodCallHandler。方法名出现在 MethodCall.method 中,参数出现在 MethodCall.arguments 中。如果方法不存在,handler 里应调用 result.notImplemented();参数格式错误则调用 result.error() 返回错误信息。Dart 端接到的是 Future<T>,成功时拿到返回值,失败时抛出 PlatformException。
就像打电话一样,MethodChannel 适合“问一句、答一句”的场景。你要是天天打电话去问天气,物业会嫌烦——这就是性能优化要讲的道理。
- 结果 Result原生端执行完毕后返回给 Dart 的值。
- 原生方法 NativeMethod原生端注册的方法处理器。
- 参数 argumentsDart 端通过 invokeMethod 传入的参数。
- 函数作用关系原生方法把参数作为输入,执行后产生结果输出。
EventChannel——订阅广播
红色按键是订阅广播。你按下去说“我要收听小区天气播报”,物业就把你登记在订阅名单里,每天早上和晚上自动播报,你不用一遍遍打电话催。不想听了,再按一下取消订阅,广播就停了。
EventChannel 解决“持续获取数据”的问题。Dart 端调用 receiveBroadcastStream() 得到一个 Stream,每次原生端有数据推过来,Stream 就会发出一个事件。原生端需要实现 StreamHandler,通过 EventSink.success() 发送数据。整个过程的体验和听广播完全一致:订阅、接收、退订。
EventChannel 的通信方向是单向的——原生推、Dart 收。原生端的 onListen 在 Dart 开始订阅时触发,onCancel 在取消订阅时触发。Dart 端可以对 Stream 使用任意操作符:listen、where、map、takeUntil 等。适合的场景包括电池电量变化、光线传感器、位置更新、系统通知等一切“主动向你报信”的场景。
广播订阅的好处是“人歇事不停”:原生端随时推送,Dart 端随时接收,适合所有实时数据流场景。
- 事件流 StreamDart 端订阅的事件流对象。
- 单个事件原生端推送的每一个事件,例如一次电量变化。
- 事件序列事件按时间顺序连续到达。
BasicMessageChannel——互发短信
绿色按键是互发短信。你给物业发一条:“麻烦把我家门口的灯修一下。”物业回一条:“好,师傅下午三点到。”一会儿你又说“改到五点了”,物业说“收到”——一来一回,没有固定格式,也不用必须等对方答复。
BasicMessageChannel 提供更自由的双向消息传递。Dart 端和原生端都可以通过 send() 发消息,也都可以注册 setMessageHandler 接收消息。它不绑定“方法名 + 参数”的结构,消息本身就是任意可编码对象。如果说 MethodChannel 是“打给客服电话的固定话术”,BasicMessageChannel 更像是你与物业之间随意发起的闲聊。
BasicMessageChannel 在构造时指定编解码器(如 StandardMessageCodec、JSONMessageCodec、StringCodec),用来定义消息的编码形式。对于 Dart 与原生需要频繁交换结构化数据的场景(如剪贴板同步、主题切换、登录态同步),相比 MethodChannel 的严格方法签名,BasicMessageChannel 更轻量、更灵活。
短信模式最贴近日常对话——发消息、收消息、回消息,双方地位对等、语气自由,适合持续双向沟通的场合。
- 消息 MessageDart 或原生端发出的消息内容。
- 处理函数 Handle接收端注册的消息处理器。
- 回复 Reply处理器返回给发送方的响应。
- 收发关系一个消息经过处理器,便得到一条回复。
自定义插件——安装新分机
你觉得天天靠物业对讲机转达太麻烦,想让物业直接给你装一台专属分机,专门对接你常用的市政服务。这台分机就是“自定义插件”。装好之后,不仅你自己能用,整栋楼的邻居都能直接拨这台分机。
自定义插件(Plugin)本质上是把“通道 + 原生实现 + Dart 封装”打包成一个可复用的独立模块。团队里任何 Flutter 工程都能通过 pubspec.yaml 依赖它,像安装电话分机一样即插即用。比如 shared_preferences、path_provider 这些知名插件,都是这么封装出来的。
创建一个 Flutter 插件工程,典型命令是 flutter create --template=plugin。Dart 端暴露一个类,内部持有 MethodChannel 或 EventChannel,封装好业务方法;Android 端实现 FlutterPlugin,在 onAttachedToEngine 里注册通道和 handler;iOS 端实现 FlutterPlugin,用 register(with:) 注册。插件发布后,其他工程只需在 pubspec 里声明依赖,就能直接调用,完全不用关心原生实现细节。
装好分机后,所有业务方共用这台电话,不用每个人都在物业台前排队接线——这就是插件提升复用价值的本质。
- 插件 PluginDart 端与原生端代码的打包单元。
- 映射符号表示插件在注册时将 handler 挂载到通道上。
- 通道名 name插件使用的唯一通道标识,如 "com.example.battery"。
线程与异步——接线员的调度密码
对讲机总机房的接线员们都很忙。住户打完电话后,接线员不会直接跑到住户家里去干活,而是先在后台记录、查询、整理,然后把结果通过话筒回复给住户。住户这边的电话线(主线程)不会占着一直等。
Platform Channel 的跨线程模型与此类似。在原生端,通道回调默认运行在主线程(Android 的 main thread / iOS 的 main thread)。所以不能在回调里做耗时操作,否则会卡住 UI。正确做法是切换到后台线程(Kotlin 的 Thread/Coroutine,Swift 的 DispatchQueue.global())执行,完成后切回主线程再回调结果。
Dart 端也可以配合 Isolate 处理计算密集型任务,用 SendPort/ReceivePort 与主 Isolate 通信。异步方面,MethodChannel 的 invokeMethod 返回 Future,配合 async/await 不会阻塞 UI;EventChannel 的 Stream 本身是异步的。记住一个原则:任何一方都不应该在主线程上做重量级操作,就像接线员不应该让住户在电话里干等十分钟。
记住“接线员不回住户家干活”——跨线程的关键是把活分派给合适的人,而不是让总机房的电话线一直占线。
- 平台线程原生端通道回调所在的线程。
- UI 线程渲染界面的主线程。
- 两者不相等代表两个不同线程,不能直接互相访问 UI 状态。
- 推导结论耗时操作必须在后台线程完成,再切回主线程做结果回调。
性能优化——别什么事都打电话
楼道门口贴了一张告示:“各位居民,请勿频繁拨打物业电话查询同一信息,系统会定期播报,请自行留意。”物业想要的很朴素:少打电话、说重点、别占线。
Platform Channel 的每次通信都有固定开销:编解码、线程切换、消息拷贝。频繁的小调用比一次批量调用耗费高得多。所以优化的核心思路就是:降低通信频次、增大单次有效信息量。就像与其打十次电话问十个问题,不如打一次电话把十个问题一次问完。
常用优化手段包括:合并多次相关调用为一次(如一次传回电池、信号、充电状态三个值);对高频事件做节流(throttle)或聚合(buffer),如传感器数据可以 100ms 取一次样再上报;避免在通道里传输大文件,应该传文件路径或使用共享内存;对不使用的 EventChannel 及时取消订阅,释放原生资源;在原生端处理好线程,避免主线程排队等待。
看完告示就明白了:能听广播就别挨个打电话,能一次说三件事就别跑三趟,这才是和原生世界相处的正确打开方式。
- 总耗时一段时间内所有通道通信消耗的总时间。
- 通信次数调用通道的总次数。
- 单次开销每次通信的编解码、线程切换等固定开销。
- 传输时间消息体本身传输与处理的时间。
- 线性叠加次数越多,固定开销越积越大;减少 n 和单次开销,总耗时显著下降。
AI 应用场景
实时电池电量与充电状态监测
阶段:数据接入与设备能力调用
解决的问题:传统跨平台应用要获取电池状态,需要在 iOS 和 Android 各写一套原生代码,维护成本高。AI 应用(如健康监测 App)需要持续获取电量变化来动态调度后台任务。通过 EventChannel,Dart 端只需订阅一个事件流,两端原生能力统一封装成插件,上层 AI 逻辑专注数据处理即可。
具体案例:一个 AI 健身 App 需要实时监测运动中手机电量下降趋势,以决定是否降低传感器采样频率。项目用 EventChannel 订阅电量广播,Dart 端用 Stream.where 过滤出有效电量变化事件,再交由 AI 模型预测剩余可用时间。
端侧 AI 模型识别插件
阶段:端侧推理与设备能力集成
解决的问题:AI 应用常需调用原生平台能力(相机、相册、TFLite/CoreML 推理)。直接写原生代码不利于跨平台复用。通过自定义插件(内部使用 MethodChannel),把 TFLite/CoreML 模型封装成统一 Dart API,调用方无需关心底层是 Android 还是 iOS。
具体案例:团队开发一款 OCR 识别应用,Android 端用 TFLite、iOS 端用 CoreML。自定义插件内部用 MethodChannel 暴露 recognize(byteData) 方法,Dart 端传图片字节流,原生端解码、送入模型识别,返回 JSON 识别结果。
AI 对话应用的剪贴板联动
阶段:多端协同与上下文同步
解决的问题:AI 对话应用需要监听系统剪贴板变化、与原生输入法协同。BasicMessageChannel 的双向消息能力适合这种自由、持续的消息同步,两端地位对等、随时对话。
具体案例:AI 写作助手在用户复制文本时,需要让 Flutter 端立刻感知并弹出“AI 润色”按钮。原生端监听系统剪贴板变化,通过 BasicMessageChannel 推送给 Dart;Dart 端处理后回传友好提示,两端持续双向会话,实现无缝联动。
Python 演示
"""模拟 Flutter Platform Channel 的消息编解码与三种通道的分发流程"""import json class MessageCodec: """模拟 StandardMessageCodec, 支持基础类型与字典列表""" @staticmethod def encode(obj): if isinstance(obj, (str, int, float, bool, list, dict)) or obj is None: return json.dumps(obj).encode("utf-8") raise TypeError("unsupported type: %s" % type(obj)) @staticmethod def decode(data): return json.loads(data.decode("utf-8")) class MethodChannel: """方法调用通道: 请求 -> 原生执行 -> 响应""" def __init__(self, name): self.name = name self.handler = None def set_method_call_handler(self, fn): self.handler = fn def invoke_method(self, method, args): if not self.handler: raise RuntimeError("MissingPluginException: no handler for %s" % self.name) return self.handler(method, args) class EventChannel: """事件通道: 原生持续向 Dart 推送事件""" def __init__(self, name): self.name = name self.listeners = [] def listen(self, callback): self.listeners.append(callback) def push_event(self, event): encoded = MessageCodec.encode(event) for cb in self.listeners: cb(MessageCodec.decode(encoded)) class BasicMessageChannel: """基础消息通道: 双向消息, 双方平等对话""" def __init__(self, name): self.name = name self.handler = None def set_message_handler(self, fn): self.handler = fn def send(self, message): if not self.handler: raise RuntimeError("no handler for channel %s" % self.name) return self.handler(message) def main(): method_ch = MethodChannel("com.example.battery") method_ch.set_method_call_handler(lambda method, args: 86 if method == "getBatteryLevel" else -1) battery = method_ch.invoke_method("getBatteryLevel", None) print("[MethodChannel] battery level = %d%%" % battery) event_ch = EventChannel("com.example.sensor") event_ch.listen(lambda e: print("[EventChannel] receive event: %s" % e)) for i in range(3): event_ch.push_event({"x": i + 1, "y": (i + 1) * 2}) basic_ch = BasicMessageChannel("com.example.chat") basic_ch.set_message_handler(lambda msg: "echo: " + msg) reply = basic_ch.send("hello from dart") print("[BasicMessageChannel] reply = %s" % reply) if __name__ == "__main__": main()
class MethodChannel:封装方法调用通道,模拟“请求-响应”通信。MessageCodec.encode将 Dart 侧对象编码为二进制字节流。MessageCodec.decode将字节流还原为原生侧对象。method_ch.set_method_call_handler(lambda method, args: 86 if method == "getBatteryLevel" else -1)原生端注册方法处理器,只有方法名匹配时才返回有效电量。battery = method_ch.invoke_method("getBatteryLevel", None)Dart 端发起方法调用,像打电话一样等待回复。event_ch.listen(...)Dart 端订阅事件流,被动接收推送。event_ch.push_event(...)原生端主动推送事件,模拟 EventChannel 单向流。basic_ch.set_message_handler(lambda msg: "echo: " + msg)原生端注册消息处理器,随时回复。reply = basic_ch.send("hello from dart")Dart 端发送基础消息,获得异步回复。
常见误区
误区好多同学觉得 MethodChannel、EventChannel 和 BasicMessageChannel 底层都一样,随便用哪个都行。我上次用 MethodChannel 收传感器数据也成功了,没什么区别嘛。
正解底层虽共用同一套消息管线,但三种通道的会话模式完全不同。MethodChannel 是“一问一答”,EventChannel 是“单向推送”,BasicMessageChannel 是“双向自由消息”。用 MethodChannel 模拟推送需要不断轮询调用,白白增加通信次数;用 EventChannel 传一次性结果又会让代码绕远路。就像打电话、听广播、发短信,形式不同决定适用场景不同。
为何常见:初学时往往先接触 MethodChannel,对它最熟悉,于是把它当万能钥匙。加上偶尔能跑通 Demo,就更不会质疑了。
误区我在 Dart 里 new 了一个 User 对象,直接传给原生端,原生也“收到”了呀,为什么说不能传?
正解用 StandardMessageCodec 直接传自定义对象会抛异常。你所谓的“收到”,是因为代码里碰巧把 User 先转成了 Map 或 JSON 字符串。Platform Channel 的编解码器只认识基础类型,自定义对象必须手动序列化成 Map、List 或二进制后传递,原生端再反序列化还原。
为何常见:现代语言普遍支持对象序列化(JSON、Kryo),容易让人假设 Platform Channel 也自动支持任意对象。
误区EventChannel 既然带“通道”两个字,那应该是双向的吧,我也可以在 Dart 端调用它给原生发消息。
正解EventChannel 的数据方向是单向的:原生端通过 EventSink 推送,Dart 端只负责订阅接收。要在 Dart 端主动向原生发起数据,应该用 MethodChannel(请求)或 BasicMessageChannel(双向)。如果用错方向,Dart 端根本没有可供调用的发送接口。
为何常见:“通道”这个名字容易造成“双向”的直觉,加上 MethodChannel 又确实有来有回,就更容易混淆 EventChannel 的方向性。
误区通道是跨线程通信嘛,那原生端的回调应该自动在子线程吧,我做耗时操作应该没关系。
正解原生端 MethodChannel 回调默认运行在主线程(Android 与 iOS 都是)。如果在回调里直接做耗时操作,UI 会掉帧甚至卡死。正确做法是把耗时任务分发到后台线程,完成后切回主线程再回调 Result。
为何常见:对“跨线程通信”只停留在字面理解,没实际测试主线程卡顿,就不会意识到回调线程的问题。
误区通道调用就像函数调用一样轻量,我把它放在循环里频繁调用应该没事吧?
正解每次通道调用都有消息编解码、线程切换、内存拷贝等固定开销。100 次独立调用远大于把 100 条数据合成 1 条批量传输的开销。高频场景下应合并调用、节流或批量上报;大文件应传路径而非内容。这是端侧 AI 应用中频繁数据交互优化的核心思路。
为何常见:初用通道时数据量小、测试机型性能好,感觉不到延迟,就忽略了固定开销的累积效应。
面试题
Q1. MethodChannel 采用哪种通信模式?
- A.订阅-推送模式
- B.请求-响应模式← 正确答案
- C.广播-接收模式
- D.文件-传输模式
答案:B。MethodChannel 就像打电话:Dart 端发起请求,原生端处理完返回结果,一问一答,所以是请求-响应模式。订阅-推送、广播-接收是 EventChannel 的特点;文件-传输是干扰项,通道并非为传文件而设计。
Q2. 需要持续接收原生端推送的传感器数据,应该使用哪种通道?
- A.方法调用通道
- B.网络通信通道
- C.事件推送通道← 正确答案
- D.数据库轮询
答案:C。传感器数据是持续产生的实时数据流,EventChannel 的“订阅-推送”模式正好契合。方法调用通道适合一次性请求;网络通信通道和数据库轮询都不是 Flutter 原生的通道类型。
Q3. MethodChannel 调用原生方法时,参数如何传给原生端?
- A.写入本地缓存文件
- B.作为方法第二参数← 正确答案
- C.拼接在方法名称中
- D.通过环境变量注入
答案:B。invokeMethod(String method, [Object? arguments]) 的第二个参数就是传给原生端的参数。原生端通过 methodCall.arguments 获取。缓存文件、环境变量都是旁门左道,通道本身就是传参的正规渠道。
Q4. Android 原生端 MethodChannel 方法调用默认运行在哪个线程?
- A.主线程执行← 正确答案
- B.后台线程
- C.IO 线程组
- D.线程池调度
答案:A。Platform Channel 的默认行为是让原生端回调在主线程执行。如果在这里做耗时操作会卡住 UI,所以需要切换后台线程处理重任务。就像接线员在总机台接电话,而不是跑到住户家里干活。
Q5. BasicMessageChannel 最大的特点是什么?
- A.只能单向传输
- B.支持持续双向← 正确答案
- C.不需要通道名
- D.只能传字符串
答案:B。BasicMessageChannel 支持两端随时发消息、随时回消息,是三种通道中最自由的一种。MethodChannel 虽然也有响应,但必须以方法签名为框架;EventChannel 方向单向;省略通道名会导致两端无法配对。
Q6. 调用一个尚未注册对应原生处理器的通道,会发生什么?
- A.编译期直接报错
- B.运行时抛异常报错← 正确答案
- C.返回空对象不报错
- D.自动创建一个通道
答案:B。通道在 Dart 端创建时不会校验原生端是否存在处理器。真正 invoke 时才执行原生查找,找不到对应的 MethodChannel,引擎会抛出 MissingPluginException。这是典型的运行时错误,不是编译期错误。
Q7. Flutter Platform Channel 支持哪些类型的数据传递?
- A.整数、浮点数← 正确答案
- B.字符串、布尔值← 正确答案
- C.任意自定义对象
- D.基础类型的列表和字典← 正确答案
答案:ABD。StandardMessageCodec 支持基础类型、二进制、List 和 Map 等组合结构。任意自定义对象并不能直接传递,必须先手动序列化为 Map、List 或二进制,原生端再还原。选项 C 是常见误区。
Q8. 下列哪些做法可以优化 Platform Channel 的性能?
- A.合并多次通信← 正确答案
- B.高频事件节流← 正确答案
- C.避免主线程耗时← 正确答案
- D.传输超大消息
答案:ABC。合并多次调用能降低固定开销的累积,节流能减少无效通信,避免主线程耗时能减少 UI 卡顿。传输超大消息本身也会增加传输和编解码负担,并非优化手段,大文件应传路径或分片发送。
Q9. 关于 EventChannel,下列说法正确的有哪些?
- A.Dart 端通过流订阅← 正确答案
- B.取消触发关闭回调← 正确答案
- C.原生端用事件发射← 正确答案
- D.支持从 Dart 推数据
答案:ABC。EventChannel 使用 receiveBroadcastStream() 返回 Stream 供 Dart 订阅;取消订阅会触发原生端 onCancel 回调;原生端通过 EventSink 发射事件。Dart 端没有向原生推送数据的接口,D 是错的。
Q10. 需要在 Dart 与原生之间传递自定义对象,最恰当的做法是?
- A.手动序列化后传递← 正确答案
- B.直接传递对象引用
- C.反射机制自动转换
- D.全局变量临时传递
答案:A。Platform Channel 的编解码器只认识基础类型,自定义对象必须提前手动序列化成 Map 或二进制,原生端拿到后再反序列化。对象引用是内存层面的概念,跨进程/跨线程不适用;反射无法覆盖两端异构语言的类型差异;全局变量只限于单端内部。