Flutter 与 Android Native 数据互通完整方案,整体分两大类:单次即时通信(MethodChannel)、数据流持续监听(EventChannel)、共享内存持久化数据(文件/SP/数据库)。
通信底层:Flutter 通过 Platform Channel 和原生 JNI 桥接,本质是字符串二进制传输。
一、三种Channel区别
1. MethodChannel:双向单次调用(最常用)
Flutter 主动调用原生方法,原生回调结果;原生也可主动调用 Flutter。适合传普通数据、调用原生功能。2. EventChannel:单向持续数据流
原生持续推送数据到 Flutter(传感器、定位、蓝牙、监听网络变化),Flutter 只监听,不回传。3. BasicMessageChannel:自由收发字符串/二进制
适合传输 json、字节数组,自定义消息格式,灵活性最高。
数据传输格式:统一传 JSON 字符串,两边解析。
二、MethodChannel (Flutter)
1)Flutter 端(Dart)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
import 'package:flutter/services.dart';
class NativeBridge{
// 通道名称,两端必须完全一致
static const MethodChannel _channel = MethodChannel("com.app.native/bridge");
/// Flutter调用Android原生,传参,接收返回值
static Future<Map?> callAndroid(Map params) async {
try {
// invokeMethod(方法名, 参数),参数直接传map,底层自动序列化
String res = await _channel.invokeMethod("getData", params);
// 解析json
return json.decode(res);
} catch (e) {
return null;
}
}
/// Android主动调用Flutter方法
static void initNativeCallBack() {
_channel.setMethodCallHandler((call) async {
switch (call.method) {
case "pushDataFromNative":
// 原生传来的数据 call.arguments
Map data = call.arguments;
print("原生推送:$data");
return "收到";
}
return null;
});
}
}
2)Android 原生端(Kotlin)
在 MainActivity 中注册通道,必须在 onCreate 初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
// 和Flutter通道名保持一致
private val CHANNEL = "com.app.native/bridge"
overridefun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// 注册通道
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
when (call.method) {
// Flutter调用原生的方法名
"getData" -> {
// 获取Flutter传过来的参数
val params = call.arguments as Map<String, Any>
// 业务处理,组装返回数据
val map = hashMapOf<String, Any>("code" to 200, "msg" to "原生返回数据")
// 回调给Flutter
result.success(gson.toJson(map))
}
else -> result.notImplemented()
}
}
}
// Android主动发送数据给Flutter
fun sendToFlutter(){
MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CHANNEL)
.invokeMethod("pushDataFromNative", mapOf("name" to "测试数据"))
}
}
传输数据类型限制
可以直接传递:String、Int、Boolean、List、Map,底层会自动序列化,不要直接传对象,复杂对象统一用JSON字符串。
三、EventChannel 持续推送(原生不停发数据)
适用场景:实时定位、陀螺仪、日志推送。
1. Android 不断发送数据 2. Flutter 只监听。
Android端
1 2 3 4 5 6 7 8
EventChannel(flutterEngine.dartExecutor.binaryMessenger, "com.app.native/event")
.setStreamHandler(object : EventChannel.StreamHandler {
overridefun onListen(arguments: Any?, events: EventChannel.EventSink?) {
// 定时持续推送
events?.success("实时数据")
}
overridefun onCancel(arguments: Any?) {}
})
Flutter端
1 2 3 4 5
static const EventChannel _eventChannel = EventChannel("com.app.native/event");
_streamSub = _eventChannel.receiveBroadcastStream().listen((data){
print("原生实时数据:$data");
});
四、持久化共享数据(全局长期共用)
Channel 适合临时即时通信;如果需要全局缓存,两边随时读取,3种方案:
方案1:SharedPreferences(最简单)
Android 读写SP;Flutter 使用 shared_preferences 插件,共用系统同一个SP文件。
注意:Android 10+ 默认文件隔离,需要配置相同文件名,才能共用。
方案2:本地文件
存 json 文件到应用私有目录。
• Android: context.filesDir• Flutter:通过 MethodChannel 获取原生文件路径,直接读写同一个文件。
方案3:数据库
Android 操作 SQLite;Flutter 不直接访问数据库,通过 MethodChannel 调用原生读写。
五、三种方案选型建议
1. 单次交互、临时传参 → MethodChannel(优先用) 2. 原生持续推送实时数据 → EventChannel 3. 全局缓存、两边随时读取 → SP / 本地文件 4. 传输大字节流(图片、文件) → BasicMessageChannel 传 Uint8List
六、踩坑重点
1. 两端通道名称、方法名必须一字不差,大小写敏感;错一个直接收不到。 2. Android 新版 Flutter 只用 configureFlutterEngine注册,不要用旧版 GeneratedPluginRegistrant。3. 原生不能在子线程直接调用 invokeMethod,要切到主线程。 4. 页面销毁时,Flutter 要取消监听,防止内存泄漏。
夜雨聆风