Flutter 中与原生通信方式

在 Flutter 中与原生平台(Android/iOS)通信主要通过以下几种方式实现,每种方式适用于不同场景:


1. 平台通道(Platform Channel)(最常用)

用途:Flutter 与原生平台双向通信
核心类

  • MethodChannel:方法调用(最常用)
  • EventChannel:事件流通信(如传感器数据)
  • BasicMessageChannel:基础数据传递(较少用)

示例:调用原生 Toast

Flutter 端代码
import 'package:flutter/services.dart';

// 创建 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("调用失败: ${e.message}");
  }
}

// 调用
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. 平台插件(Plugins)

用途:复用社区封装好的原生功能
示例插件

  • camera:访问摄像头
  • geolocator:获取位置
  • shared_preferences:本地存储

使用方式

# 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)

用途:直接调用 C/C++/Rust 等原生库
适用场景:高性能计算、复用现有原生库
示例:调用 C 函数

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. 平台视图(PlatformView)

用途:在 Flutter 中嵌入原生 UI 组件
实现方式

  • AndroidAndroidView
  • iOSUiKitView

示例:嵌入 WebView

// flutter_inappwebview 插件示例
InAppWebView(
  initialUrlRequest: URLRequest(url: Uri.parse("https://flutter.dev")),
)

5. 后台通道(Background Channel)

用途:在后台服务中与 Flutter 通信
实现:通过 BackgroundFetchWorkmanager 插件


各方案对比

方式 适用场景 性能 复杂度 维护性
Platform Channel 通用双向通信(90%场景) ★★★★
Plugins 复用社区封装功能 依赖插件 ★★★★★
FFI 高性能计算/C++库集成 极高 ★★
PlatformView 嵌入复杂原生UI(如地图、WebView) 较低 ★★★

开发建议

  1. 优先使用插件:避免重复造轮子(pub.dev 搜索现有方案)
  2. 复杂逻辑原生实现:通过 MethodChannel 调用
  3. 性能敏感场景:考虑 FFI
  4. 通信数据量小:JSON 格式传递(平台通道支持自动序列化)
  5. 错误处理:始终捕获 PlatformException

调试技巧

  • 查看通道日志
    flutter run -v
    
  • 检查通道名称:确保 Flutter 和原生端完全一致(大小写敏感)
  • 数据类型匹配:Android/iOS 和 Flutter 的数据类型需对应(如 MapDictionary

掌握这些通信方式后,可以灵活实现 Flutter 与原生平台的能力互补!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容