Flutter 與原生之間的通信主要基于通道機制,包括 MethodChannel、EventChannel 和 BasicMessageChannel。
- MethodChannel:用于 Flutter 與原生之間的方法調用,實現雙向通信,適合一次性的方法調用并獲取返回值,如 Flutter調用原生拍照功能并獲取照片路徑。
- EventChannel:主要用于原生向 Flutter 發送數據流,例如原生端將傳感器數據實時傳遞給 Flutter 端。
- BasicMessageChannel:用于 Flutter 與原生之間傳遞字符串、二進制數據等基本類型的數據,可進行簡單的數據交換。
1. Flutter 調用原生
Flutter 端代碼
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key}); Widget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('Flutter 調用原生示例'),),body: Center(child: ElevatedButton(onPressed: () async {const platform = MethodChannel('com.example.flutter_native');try {final String result = await platform.invokeMethod('getNativeMessage');print('原生返回的消息: $result');} on PlatformException catch (e) {print('調用原生方法失敗: ${e.message}');}},child: const Text('調用原生方法'),),),),);}
}
在 Flutter 端,創建 MethodChannel 實例,使用 invokeMethod 方法調用原生端的 getNativeMessage 方法,并處理返回結果。
安卓原生端代碼(Kotlin)
package com.example.flutter_nativeimport android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannelclass MainActivity : FlutterActivity() {private val CHANNEL = "com.example.flutter_native"override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->if (call.method == "getNativeMessage") {result.success("這是來自安卓原生的消息")} else {result.notImplemented()}}}
}
在安卓端,創建 MethodChannel 實例,設置方法調用處理程序,當接收到 getNativeMessage 方法調用時,返回消息給 Flutter 端。
iOS 原生端代碼(Swift)
import Flutter
import UIKit@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet channel = FlutterMethodChannel(name: "com.example.flutter_native", binaryMessenger: controller.binaryMessenger)channel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) inif call.method == "getNativeMessage" {result("這是來自 iOS 原生的消息")} else {result(FlutterMethodNotImplemented)}}GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}
}
在 iOS 端,創建 FlutterMethodChannel 實例,設置方法調用處理程序,處理 getNativeMessage 方法調用并返回消息給 Flutter 端。
2. 原生調用 Flutter
Flutter 端代碼
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key}); Widget build(BuildContext context) {const platform = MethodChannel('com.example.native_flutter');platform.setMethodCallHandler((call) async {if (call.method == "getFlutterMessage") {return "這是來自 Flutter 的消息";}return null;});return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('原生調用 Flutter 示例'),),body: const Center(child: Text('等待原生調用...'),),),);}
}
在 Flutter 端,創建 MethodChannel 實例,使用 setMethodCallHandler 方法設置處理原生調用的回調,當接收到 getFlutterMessage 方法調用時,返回消息給原生端。
安卓原生端代碼(Kotlin)
package com.example.native_flutterimport android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannelclass MainActivity : FlutterActivity() {private val CHANNEL = "com.example.native_flutter"override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)channel.invokeMethod("getFlutterMessage", null) { result ->println("Flutter 返回的消息: $result")}}
}
在安卓端,創建 MethodChannel 實例,使用 invokeMethod 方法調用 Flutter 端的 getFlutterMessage 方法,并處理返回結果。
iOS 原生端代碼(Swift)
import Flutter
import UIKit@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet channel = FlutterMethodChannel(name: "com.example.native_flutter", binaryMessenger: controller.binaryMessenger)channel.invokeMethod("getFlutterMessage", arguments: nil) { (result) inif let message = result as? String {print("Flutter 返回的消息: \(message)")}}GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}
}
在 iOS 端,創建 FlutterMethodChannel 實例,使用 invokeMethod 方法調用 Flutter 端的 getFlutterMessage 方法,并處理返回結果。
3. EventChannel和BasicMessageChannel
EventChannel和BasicMessageChannel跟上面MethodChannel大同小異。
EventChannel
Flutter端
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key}); Widget build(BuildContext context) {const eventChannel = EventChannel('com.example.event_channel');eventChannel.receiveBroadcastStream().listen((event) {print('接收到原生端的事件: $event');}, onError: (error) {print('接收事件時出錯: $error');});return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('EventChannel 示例'),),body: const Center(child: Text('等待原生端發送事件...'),),),);}
}
在 Flutter 端,創建 EventChannel 實例,使用 receiveBroadcastStream 方法接收原生端發送的數據流,并通過 listen 方法監聽事件。
安卓端
package com.example.event_channelimport android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannelclass MainActivity : FlutterActivity() {private val CHANNEL = "com.example.event_channel"override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)EventChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setStreamHandler(object : EventChannel.StreamHandler {private var eventSink: EventChannel.EventSink? = nulloverride fun onListen(arguments: Any?, events: EventChannel.EventSink?) {eventSink = events// 模擬每隔 1 秒發送一個事件val timer = android.os.Handler()val runnable = object : Runnable {var counter = 0override fun run() {eventSink?.success("事件 $counter")counter++timer.postDelayed(this, 1000)}}timer.post(runnable)}override fun onCancel(arguments: Any?) {eventSink = null}})}
}
在安卓端,創建 EventChannel 實例,設置 StreamHandler,在 onListen 方法中模擬每隔 1 秒向 Flutter 端發送一個事件,在 onCancel 方法中取消事件發送。
iOS 原生端代碼(Swift)
import Flutter
import UIKit@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet eventChannel = FlutterEventChannel(name: "com.example.event_channel", binaryMessenger: controller.binaryMessenger)eventChannel.setStreamHandler(MyStreamHandler())GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}
}class MyStreamHandler: NSObject, FlutterStreamHandler {var eventSink: FlutterEventSink?var timer: Timer?func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {eventSink = events// 模擬每隔 1 秒發送一個事件timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ invar counter = 0self?.eventSink?("事件 \(counter)")counter += 1}return nil}func onCancel(withArguments arguments: Any?) -> FlutterError? {timer?.invalidate()timer = nileventSink = nilreturn nil}
}
在 iOS 端,創建 FlutterEventChannel 實例,設置 StreamHandler,在 onListen 方法中模擬每隔 1 秒向 Flutter 端發送一個事件,在 onCancel 方法中取消事件發送。
BasicMessageChannel
BasicMessageChannel 用于 Flutter 與原生之間傳遞字符串、二進制數據等基本類型的數據,是一種雙向通信機制,適用于簡單的數據交換場景,比如傳遞配置信息、狀態信息等。雙方可以互相發送和接收數據。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key}); Widget build(BuildContext context) {const messageChannel = BasicMessageChannel<String>('com.example.message_channel', StringCodec());messageChannel.send('來自 Flutter 的消息').then((reply) {if (reply != null) {print('收到原生端的回復: $reply');}});messageChannel.setMessageHandler((message) async {print('收到原生端的消息: $message');return 'Flutter 已收到消息';});return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('BasicMessageChannel 示例'),),body: const Center(child: Text('進行消息通信...'),),),);}
}
在 Flutter 端,創建 BasicMessageChannel 實例,使用 send 方法向原生端發送消息,并處理原生端的回復;使用 setMessageHandler 方法設置處理原生端發送消息的回調。
安卓原生端代碼(Kotlin)
package com.example.message_channelimport android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.StringCodecclass MainActivity : FlutterActivity() {private val CHANNEL = "com.example.message_channel"override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)val messageChannel = BasicMessageChannel<String>(flutterEngine.dartExecutor.binaryMessenger,CHANNEL,StringCodec())messageChannel.send("來自安卓原生的消息") { reply ->if (reply != null) {println("收到 Flutter 的回復: $reply")}}messageChannel.setMessageHandler { message, reply ->println("收到 Flutter 的消息: $message")reply.reply("安卓原生已收到消息")}}
}
在安卓端,創建 BasicMessageChannel 實例,使用 send 方法向 Flutter 端發送消息,并處理 Flutter 端的回復;使用 setMessageHandler 方法設置處理 Flutter 端發送消息的回調。
iOS 原生端代碼(Swift)
import Flutter
import UIKit@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet messageChannel = FlutterBasicMessageChannel(name: "com.example.message_channel", binaryMessenger: controller.binaryMessenger, codec: FlutterStringCodec.sharedInstance())messageChannel.sendMessage("來自 iOS 原生的消息") { (reply) inif let replyMessage = reply as? String {print("收到 Flutter 的回復: \(replyMessage)")}}messageChannel.setMessageHandler { (message, reply) inif let message = message as? String {print("收到 Flutter 的消息: \(message)")reply("iOS 原生已收到消息")}}GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}
}
在 iOS 端,創建 FlutterBasicMessageChannel 實例,使用 sendMessage 方法向 Flutter 端發送消息,并處理 Flutter 端的回復;使用 setMessageHandler 方法設置處理 Flutter 端發送消息的回調。
另外:采用信鴿pigeons三方庫通信也是一個不錯的選擇