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_native
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class 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! FlutterViewController
let channel = FlutterMethodChannel(name: "com.example.flutter_native", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in
if 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_flutter
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class 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! FlutterViewController
let channel = FlutterMethodChannel(name: "com.example.native_flutter", binaryMessenger: controller.binaryMessenger)
channel.invokeMethod("getFlutterMessage", arguments: nil) { (result) in
if 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_channel
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
class 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? = null
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
eventSink = events
// 模拟每隔 1 秒发送一个事件
val timer = android.os.Handler()
val runnable = object : Runnable {
var counter = 0
override 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! FlutterViewController
let 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] _ in
var counter = 0
self?.eventSink?("事件 \(counter)")
counter += 1
}
return nil
}
func onCancel(withArguments arguments: Any?) -> FlutterError? {
timer?.invalidate()
timer = nil
eventSink = nil
return 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_channel
import 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.StringCodec
class 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! FlutterViewController
let messageChannel = FlutterBasicMessageChannel(name: "com.example.message_channel", binaryMessenger: controller.binaryMessenger, codec: FlutterStringCodec.sharedInstance())
messageChannel.sendMessage("来自 iOS 原生的消息") { (reply) in
if let replyMessage = reply as? String {
print("收到 Flutter 的回复: \(replyMessage)")
}
}
messageChannel.setMessageHandler { (message, reply) in
if 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三方库通信也是一个不错的选择