在 Flutter 中與原生平臺(tái)(Android/iOS)通信主要通過(guò)以下幾種方式實(shí)現(xiàn),每種方式適用于不同場(chǎng)景:
1. 平臺(tái)通道(Platform Channel)(最常用)
用途:Flutter 與原生平臺(tái)雙向通信
核心類:
-
MethodChannel:方法調(diào)用(最常用) -
EventChannel:事件流通信(如傳感器數(shù)據(jù)) -
BasicMessageChannel:基礎(chǔ)數(shù)據(jù)傳遞(較少用)
示例:調(diào)用原生 Toast
Flutter 端代碼:
import 'package:flutter/services.dart';
// 創(chuàng)建 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("調(diào)用失敗: ${e.message}");
}
}
// 調(diào)用
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. 平臺(tái)插件(Plugins)
用途:復(fù)用社區(qū)封裝好的原生功能
示例插件:
-
camera:訪問(wèn)攝像頭 -
geolocator:獲取位置 -
shared_preferences:本地存儲(chǔ)
使用方式:
# 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)
用途:直接調(diào)用 C/C++/Rust 等原生庫(kù)
適用場(chǎng)景:高性能計(jì)算、復(fù)用現(xiàn)有原生庫(kù)
示例:調(diào)用 C 函數(shù)
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. 平臺(tái)視圖(PlatformView)
用途:在 Flutter 中嵌入原生 UI 組件
實(shí)現(xiàn)方式:
-
Android:
AndroidView -
iOS:
UiKitView
示例:嵌入 WebView
// flutter_inappwebview 插件示例
InAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse("https://flutter.dev")),
)
5. 后臺(tái)通道(Background Channel)
用途:在后臺(tái)服務(wù)中與 Flutter 通信
實(shí)現(xiàn):通過(guò) BackgroundFetch 或 Workmanager 插件
各方案對(duì)比
| 方式 | 適用場(chǎng)景 | 性能 | 復(fù)雜度 | 維護(hù)性 |
|---|---|---|---|---|
| Platform Channel | 通用雙向通信(90%場(chǎng)景) | 高 | 中 | ★★★★ |
| Plugins | 復(fù)用社區(qū)封裝功能 | 依賴插件 | 低 | ★★★★★ |
| FFI | 高性能計(jì)算/C++庫(kù)集成 | 極高 | 高 | ★★ |
| PlatformView | 嵌入復(fù)雜原生UI(如地圖、WebView) | 較低 | 高 | ★★★ |
開(kāi)發(fā)建議
- 優(yōu)先使用插件:避免重復(fù)造輪子(pub.dev 搜索現(xiàn)有方案)
-
復(fù)雜邏輯原生實(shí)現(xiàn):通過(guò)
MethodChannel調(diào)用 - 性能敏感場(chǎng)景:考慮 FFI
- 通信數(shù)據(jù)量小:JSON 格式傳遞(平臺(tái)通道支持自動(dòng)序列化)
-
錯(cuò)誤處理:始終捕獲
PlatformException
調(diào)試技巧
-
查看通道日志:
flutter run -v - 檢查通道名稱:確保 Flutter 和原生端完全一致(大小寫敏感)
-
數(shù)據(jù)類型匹配:Android/iOS 和 Flutter 的數(shù)據(jù)類型需對(duì)應(yīng)(如
Map?Dictionary)
掌握這些通信方式后,可以靈活實(shí)現(xiàn) Flutter 與原生平臺(tái)的能力互補(bǔ)!