在 Flutter 中与原生平台(Android/iOS)通信主要通过以下几种方式实现,每种方式适用于不同场景:
1. 平台通道(Platform Channel)(最常用)
用途:Flutter 与原生平台双向通信
核心类:
-
MethodChannel:方法调用(最常用) -
EventChannel:事件流通信(如传感器数据) -
BasicMessageChannel:基础数据传递(较少用)
示例:调用原生 Toast
Flutter 端代码:
import 'package:flutter/services.dart';
// 创建 MethodChannel(通道名称需与原生端一致)
const platform = MethodChannel('com.example/toast');
Future<void> showNativeToast(String message) async {
try {
await platform.invokeMethod('showToast', {'msg': message});
} on PlatformException catch (e) {
print("调用失败: ${e.message}");
}
}
// 调用
ElevatedButton(
onPressed: () => showNativeToast('Hello from Flutter!'),
child: Text('显示原生Toast'),
)
Android 端(Kotlin):
// MainActivity.kt
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example/toast").setMethodCallHandler { call, result ->
if (call.method == "showToast") {
val msg = call.argument<String>("msg")
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
result.success(null)
} else {
result.notImplemented()
}
}
}
}
iOS 端(Swift):
// AppDelegate.swift
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "com.example/toast", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
if call.method == "showToast" {
if let args = call.arguments as? [String: Any],
let msg = args["msg"] as? String {
let alert = UIAlertController(title: nil, message: msg, preferredStyle: .alert)
self.window?.rootViewController?.present(alert, animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
alert.dismiss(animated: true)
}
result(nil)
}
} else {
result(FlutterMethodNotImplemented)
}
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
2. 平台插件(Plugins)
用途:复用社区封装好的原生功能
示例插件:
-
camera:访问摄像头 -
geolocator:获取位置 -
shared_preferences:本地存储
使用方式:
# pubspec.yaml
dependencies:
url_launcher: ^6.1.0
import 'package:url_launcher/url_launcher.dart';
void launchURL() async {
if (await canLaunch('https://flutter.dev')) {
await launch('https://flutter.dev');
}
}
3. FFI(Foreign Function Interface)
用途:直接调用 C/C++/Rust 等原生库
适用场景:高性能计算、复用现有原生库
示例:调用 C 函数
C 代码(native/add.c):
int add(int a, int b) {
return a + b;
}
Flutter 端:
import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef AddFunc = Int32 Function(Int32, Int32);
void main() {
final dylib = DynamicLibrary.open('libadd.so'); // Android/iOS 需分别编译
final add = dylib.lookupFunction<AddFunc, AddFunc>('add');
print('3 + 5 = ${add(3, 5)}'); // 输出 8
}
4. 平台视图(PlatformView)
用途:在 Flutter 中嵌入原生 UI 组件
实现方式:
-
Android:
AndroidView -
iOS:
UiKitView
示例:嵌入 WebView
// flutter_inappwebview 插件示例
InAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse("https://flutter.dev")),
)
5. 后台通道(Background Channel)
用途:在后台服务中与 Flutter 通信
实现:通过 BackgroundFetch 或 Workmanager 插件
各方案对比
| 方式 | 适用场景 | 性能 | 复杂度 | 维护性 |
|---|---|---|---|---|
| Platform Channel | 通用双向通信(90%场景) | 高 | 中 | ★★★★ |
| Plugins | 复用社区封装功能 | 依赖插件 | 低 | ★★★★★ |
| FFI | 高性能计算/C++库集成 | 极高 | 高 | ★★ |
| PlatformView | 嵌入复杂原生UI(如地图、WebView) | 较低 | 高 | ★★★ |
开发建议
- 优先使用插件:避免重复造轮子(pub.dev 搜索现有方案)
-
复杂逻辑原生实现:通过
MethodChannel调用 - 性能敏感场景:考虑 FFI
- 通信数据量小:JSON 格式传递(平台通道支持自动序列化)
-
错误处理:始终捕获
PlatformException
调试技巧
-
查看通道日志:
flutter run -v - 检查通道名称:确保 Flutter 和原生端完全一致(大小写敏感)
-
数据类型匹配:Android/iOS 和 Flutter 的数据类型需对应(如
Map↔Dictionary)
掌握这些通信方式后,可以灵活实现 Flutter 与原生平台的能力互补!