ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Flutter如何与原生代码通信?Platform Channel原理与实战完全教程

Flutter如何与原生代码通信?Platform Channel原理与实战完全教程 Flutter如何与原生代码通信Platform Channel原理与实战完全教程【免费下载链接】flutterFlutter makes it easy and fast to build beautiful apps for mobile and beyond项目地址: https://gitcode.com/GitHub_Trending/flutter41/flutterFlutter 用一套 Dart 代码渲染出精美界面但相机、定位、蓝牙、系统弹窗这些能力都掌握在操作系统手里。Platform Channel平台通道就是 Flutter 与 Android/iOS 原生代码之间的通信管道——它让 Dart 侧能像调用本地函数一样调用 Java、Kotlin、Swift 代码。本文带你从零看懂它的原理并用官方电池示例完成一次完整实战。为什么需要 Platform ChannelFlutter 应用运行时由两个世界组成Dart 世界你写的业务逻辑和 UI运行在 Dart VM或 Web 的 JS 环境中原生世界AndroidJava/Kotlin或 iOSObjective-C/Swift只有它能直接调用系统 API两者是独立的进程内存空间Dart 无法直接new一个 Java 对象。Platform Channel 就是横跨这两个世界的桥它把 Dart 的消息编码成二进制字节交给引擎Engine由引擎转发给原生侧监听器处理再把结果解码后送回。整个过程全自动你只需要关心两端的代码。Platform Channel 的三层架构源码位于 platform_channel.dart包含三种能力递增的通道通道类型定义位置通信模式典型用途MethodChannelplatform_channel.dart#L291请求-响应一问一答调用原生方法并获取返回值EventChannelplatform_channel.dart#L650事件流持续推送监听电量变化、GPS 轨迹等BasicMessageChannelplatform_channel.dart#L202原始消息自定义编码、底层扩展它们底层都依赖 BinaryMessenger 发送字节流字节流的序列化规则由 message_codecs.dart 中的编码器Codec定义。一句话记忆Channel 负责说什么Codec 负责怎么打包BinaryMessenger 负责怎么送达。实战用 MethodChannel 读取电池电量仓库自带一个绝佳的教学示例 examples/platform_channel/它实现了点击按钮读取电量 实时显示充电状态。第 1 步Dart 侧发起调用static const MethodChannel methodChannel MethodChannel(samples.flutter.io/battery); final int? result await methodChannel.invokeMethod(getBatteryLevel);完整 Dart 代码见 examples/platform_channel/lib/main.dart。第 2 步Android 侧监听并响应在 MainActivity.java 中用完全相同的通道名注册处理器new MethodChannel(flutterEngine.getDartExecutor(), BATTERY_CHANNEL) .setMethodCallHandler((call, result) - { if (call.method.equals(getBatteryLevel)) { result.success(getBatteryLevel()); } else { result.notImplemented(); } });第 3 步iOS 侧监听并响应在 AppDelegate.m 中FlutterMethodChannel* batteryChannel [FlutterMethodChannel methodChannelWithName:samples.flutter.io/battery binaryMessenger:engineBridge.applicationRegistrar.messenger]; [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { if ([getBatteryLevel isEqualToString:call.method]) { result(([weakSelf getBatteryLevel])); } }];关键规则通道名samples.flutter.io/battery必须在两端一字不差。通道名就是通信地址取错地址消息就送不到。事件流实战EventChannel 持续推送EventChannel用于原生侧主动、持续地推送数据的场景。示例中 Dart 侧只需一行EventChannel(samples.flutter.io/charging) .receiveBroadcastStream().listen(_onEvent);原生侧实现StreamHandler后通过EventSink不断调用events.success(charging)推送事件——Android 侧用广播接收器监听电池变化MainActivity.java#L72-L87iOS 侧用通知中心AppDelegate.m#L74-L99。 小技巧想让原生代码反向调用Dart 方法Dart 侧用setMethodCallHandler注册处理器即可通道是双向的。哪些数据能通过通道传递默认编码器StandardMessageCodec支持这些类型的直接互传Dart 类型AndroidJavaiOSObjective-Cnull/bool/int/doublenull/Boolean/Long/DoubleNSNull/NSNumberStringStringNSStringListArrayListNSArrayMapHashMapNSDictionaryUint8List/ByteDataByteBufferFlutterStandardTypedData⚠️ 不能直接传自定义对象比如class Song。常见做法是传Map两端各自定义fromJson/toJson做序列化——这也是为什么 MethodChannel 源码注释 里专门给了一个音乐播放器的完整示例。真实应用中的 Platform ChannelPlatform Channel 远不止教学 Demo。Flutter 框架自身的系统能力全部建立在它之上内置通道常量集中在 system_channels.dart系统导航返回键、弹窗走flutter/navigation通道剪贴板读写走flutter/clipboard通道文本输入框与原生键盘的交互走flutter/textinput通道你日常使用的相机插件、支付插件、地图插件内部本质上都是一对通道名 两端实现。想要原生调用 Swift 而非 Objective-C可以参考 examples/platform_channel_swift/ 示例想深入平台视图混合渲染可看 platform_views.dart。常见坑与排查清单MissingPluginException异常几乎总是通道名拼写不一致或原生侧忘了在configureFlutterEngine中注册处理器返回 null 但不报错原生侧调用了result.notImplemented()Dart 侧需检查返回值传参抛类型错误只传 Codec 支持的基础类型自定义对象转成MapWeb 端无响应MethodChannel默认只在移动端/桌面端有原生实现Web 上需要用 JS 实现对应通道或降级处理延伸阅读通道核心实现packages/flutter/lib/src/services/platform_channel.dart二进制消息层packages/flutter/lib/src/services/binary_messenger.dart编码器定义packages/flutter/lib/src/services/message_codecs.dart完整示例与测试examples/platform_channel/README.md掌握通道名对齐、类型序列化、两端注册这三件事你就能用 Platform Channel 打通 Flutter 与任何原生能力的任督二脉 【免费下载链接】flutterFlutter makes it easy and fast to build beautiful apps for mobile and beyond项目地址: https://gitcode.com/GitHub_Trending/flutter41/flutter创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表