乐于分享
好东西不私藏

Flutter 插件中Flutter与 Android/IOS原生共享数据有几种实现?

Flutter 插件中Flutter与 Android/IOS原生共享数据有几种实现?

Flutter 与 Android Native 数据互通完整方案,整体分两大类:单次即时通信(MethodChannel)、数据流持续监听(EventChannel)、共享内存持久化数据(文件/SP/数据库)
通信底层:Flutter 通过 Platform Channel 和原生 JNI 桥接,本质是字符串二进制传输

一、三种Channel区别

  1. 1. MethodChannel:双向单次调用(最常用)
    Flutter 主动调用原生方法,原生回调结果;原生也可主动调用 Flutter。适合传普通数据、调用原生功能。
  2. 2. EventChannel:单向持续数据流
    原生持续推送数据到 Flutter(传感器、定位、蓝牙、监听网络变化),Flutter 只监听,不回传。
  3. 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. 1. Android 不断发送数据
  2. 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. 1. 单次交互、临时传参 → MethodChannel(优先用)
  2. 2. 原生持续推送实时数据 → EventChannel
  3. 3. 全局缓存、两边随时读取 → SP / 本地文件
  4. 4. 传输大字节流(图片、文件) → BasicMessageChannel 传 Uint8List

六、踩坑重点

  1. 1. 两端通道名称、方法名必须一字不差,大小写敏感;错一个直接收不到。
  2. 2. Android 新版 Flutter 只用 configureFlutterEngine 注册,不要用旧版 GeneratedPluginRegistrant。
  3. 3. 原生不能在子线程直接调用 invokeMethod,要切到主线程。
  4. 4. 页面销毁时,Flutter 要取消监听,防止内存泄漏。