Flutter 中與原生通信方式

在 Flutter 中與原生平臺(tái)(Android/iOS)通信主要通過(guò)以下幾種方式實(shí)現(xiàn),每種方式適用于不同場(chǎng)景:


1. 平臺(tái)通道(Platform Channel)(最常用)

用途:Flutter 與原生平臺(tái)雙向通信
核心類

  • MethodChannel:方法調(diào)用(最常用)
  • EventChannel:事件流通信(如傳感器數(shù)據(jù))
  • BasicMessageChannel:基礎(chǔ)數(shù)據(jù)傳遞(較少用)

示例:調(diào)用原生 Toast

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

// 創(chuàng)建 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("調(diào)用失敗: ${e.message}");
  }
}

// 調(diào)用
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. 平臺(tái)插件(Plugins)

用途:復(fù)用社區(qū)封裝好的原生功能
示例插件

  • camera:訪問(wèn)攝像頭
  • geolocator:獲取位置
  • shared_preferences:本地存儲(chǔ)

使用方式

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

用途:直接調(diào)用 C/C++/Rust 等原生庫(kù)
適用場(chǎng)景:高性能計(jì)算、復(fù)用現(xiàn)有原生庫(kù)
示例:調(diào)用 C 函數(shù)

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. 平臺(tái)視圖(PlatformView)

用途:在 Flutter 中嵌入原生 UI 組件
實(shí)現(xiàn)方式

  • AndroidAndroidView
  • iOSUiKitView

示例:嵌入 WebView

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

5. 后臺(tái)通道(Background Channel)

用途:在后臺(tái)服務(wù)中與 Flutter 通信
實(shí)現(xiàn):通過(guò) BackgroundFetchWorkmanager 插件


各方案對(duì)比

方式 適用場(chǎng)景 性能 復(fù)雜度 維護(hù)性
Platform Channel 通用雙向通信(90%場(chǎng)景) ★★★★
Plugins 復(fù)用社區(qū)封裝功能 依賴插件 ★★★★★
FFI 高性能計(jì)算/C++庫(kù)集成 極高 ★★
PlatformView 嵌入復(fù)雜原生UI(如地圖、WebView) 較低 ★★★

開(kāi)發(fā)建議

  1. 優(yōu)先使用插件:避免重復(fù)造輪子(pub.dev 搜索現(xiàn)有方案)
  2. 復(fù)雜邏輯原生實(shí)現(xiàn):通過(guò) MethodChannel 調(diào)用
  3. 性能敏感場(chǎng)景:考慮 FFI
  4. 通信數(shù)據(jù)量小:JSON 格式傳遞(平臺(tái)通道支持自動(dòng)序列化)
  5. 錯(cuò)誤處理:始終捕獲 PlatformException

調(diào)試技巧

  • 查看通道日志
    flutter run -v
    
  • 檢查通道名稱:確保 Flutter 和原生端完全一致(大小寫敏感)
  • 數(shù)據(jù)類型匹配:Android/iOS 和 Flutter 的數(shù)據(jù)類型需對(duì)應(yīng)(如 Map ? Dictionary

掌握這些通信方式后,可以靈活實(shí)現(xiàn) Flutter 與原生平臺(tái)的能力互補(bǔ)!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容