Flutter 與原生通信

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_nativeimport android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannelclass 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! FlutterViewControllerlet channel = FlutterMethodChannel(name: "com.example.flutter_native", binaryMessenger: controller.binaryMessenger)channel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) inif 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_flutterimport android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannelclass 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! FlutterViewControllerlet channel = FlutterMethodChannel(name: "com.example.native_flutter", binaryMessenger: controller.binaryMessenger)channel.invokeMethod("getFlutterMessage", arguments: nil) { (result) inif 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_channelimport android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannelclass 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? = nulloverride fun onListen(arguments: Any?, events: EventChannel.EventSink?) {eventSink = events// 模擬每隔 1 秒發送一個事件val timer = android.os.Handler()val runnable = object : Runnable {var counter = 0override 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! FlutterViewControllerlet 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] _ invar counter = 0self?.eventSink?("事件 \(counter)")counter += 1}return nil}func onCancel(withArguments arguments: Any?) -> FlutterError? {timer?.invalidate()timer = nileventSink = nilreturn 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_channelimport 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.StringCodecclass 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! FlutterViewControllerlet messageChannel = FlutterBasicMessageChannel(name: "com.example.message_channel", binaryMessenger: controller.binaryMessenger, codec: FlutterStringCodec.sharedInstance())messageChannel.sendMessage("來自 iOS 原生的消息") { (reply) inif let replyMessage = reply as? String {print("收到 Flutter 的回復: \(replyMessage)")}}messageChannel.setMessageHandler { (message, reply) inif 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三方庫通信也是一個不錯的選擇

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/77114.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77114.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/77114.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端面試-Vue篇

核心概念 Vue 3的響應式原理與Vue 2有何本質區別&#xff1f;Vue中虛擬DOM的diff算法優化策略有哪些&#xff1f;Vue組件間通信方式有哪些&#xff1f;適用場景分別是什么&#xff1f;Vue的生命周期鉤子在Composition API中如何替代&#xff1f;Vue的模板編譯過程是怎樣的&…

光刻機研發與市場現狀分析報告

1. 引言 光刻機&#xff08;Lithography Machine&#xff09;是半導體制造的核心設備&#xff0c;其技術水平和市場供應能力直接影響全球芯片產業的發展。隨著人工智能&#xff08;AI&#xff09;、5G、高性能計算&#xff08;HPC&#xff09;和自動駕駛等技術的興起&#xff0…

Missashe考研日記-day21

Missashe考研日記-day21 1 專業課408 學習時間&#xff1a;4h學習內容&#xff1a; 今天先把昨天學的內容的課后習題做了&#xff0c;整整75道啊&#xff0c;然后學了OS第二章關于CPU調度部分的內容&#xff0c;這第二章太重要了&#xff0c;以至于每一小節的內容都比較多&am…

【玩轉全棧】—— Django+vue3+訊飛星火API 實現前端頁面實時AI答復

技術棧&#xff1a;vue3 element-plus axios pinia router Django5 websocket 訊飛星火API 本文將實現一個 AI 聊天對話功能&#xff0c;將前端用戶輸入問題以及之前對話發送給后端&#xff0c;通過 api 訪問大模型&#xff0c;返回前端實時對話數據。 調用 訊飛星火API…

廣東廣州一家IPO資產重組疑點重重,信息披露真實性存疑

作者&#xff1a;Eric 來源&#xff1a;IPO魔女 4月18日&#xff0c;廣州瑞立科密汽車電子股份有限公司&#xff08;簡稱“瑞立科密”&#xff09;將接受深交所主板IPO上會審核。公司保薦機構為中信證券&#xff0c;擬募集資金為15.2162億元。 瑞立科密過往資產重組疑點重重&a…

銀河麒麟(Kylin) - V10 SP1桌面操作系統ARM64編譯QT-5.15.12版本

銀河麒麟(Kylin) - V10 SP1桌面操作系統ARM64編譯QT-5.15.12版本 原因 測試Kylin-Desktop-V10-SP1-General-Release-2303-arm64系統下&#xff0c;編譯QT-5.15.12版本已做測試。 測試環境 測試板配置 型號&#xff1a;LM-D2000-NONE-1w-V01-pc_A2150 CPU&#xff1a;飛騰D20…

查看前端項目依賴樹型結構關系圖的詳細方法,涵蓋 命令行工具 和 可視化工

以下是查看前端項目依賴樹型結構關系圖的詳細方法&#xff0c;涵蓋 命令行工具 和 可視化工具&#xff1a; 一、命令行工具生成依賴樹 1. npm # 查看項目依賴樹&#xff08;文本形式&#xff09; npm ls# 查看指定包的依賴樹 npm ls <package-name># 生成JSON格式的依…

Ollama高并發測試

本文主要來測試一下ollama的高并發能力。 具體配置如下&#xff1a; 一、Ollama默認參數執行 我們打開4個窗口&#xff0c;然后分別讓DeepSeek “給我講一個笑話” &#xff0c;看下不同窗口的答題順序。 通過答題順序可以看到&#xff0c;在不進行參數設置時&#xff0c;模…

資源管理與HPA:讓Kubernetes應用自動伸縮

引言&#xff1a;從“手動擋”到“自動駕駛” 想象我們駕駛一輛汽車&#xff0c;手動調節油門和換擋不僅費力&#xff0c;還難以應對突發狀況。我們的應用服務也一樣&#xff0c;在面對突然的流量增長&#xff0c;內存使用暴漲該如何應對。HPA&#xff08;Horizontal Pod Auto…

Windows 下 MongoDB ZIP 版本安裝指南

在開發和生產環境中&#xff0c;MongoDB 是一種非常流行的 NoSQL 數據庫&#xff0c;以其靈活性和高性能而受到開發者的青睞。對于 Windows 用戶來說&#xff0c;MongoDB 提供了多種安裝方式&#xff0c;其中 ZIP 版本因其靈活性和輕量級的特點&#xff0c;成為很多開發者的首選…

【Linux網絡與網絡編程】11.數據鏈路層mac幀協議ARP協議

前面在介紹網絡層時我們提出來過一個問題&#xff1a;主機是怎么把數據交給路由器的&#xff1f;那里我們說這是由數據鏈路層來做的。 網絡上的報文在物理結構上是以mac幀的形式流動的&#xff0c;但在邏輯上是以IP流動的&#xff0c;IP的流動是需要mac幀支持的。 數據鏈路層解…

多模態思維鏈AI醫療編程:從計算可持續性到開放域推理的系統性解決方案

多模態思維鏈AI醫療編程:從計算可持續性到開放域推理的系統性解決方案 醫療AI領域的多模態思維鏈技術正在重塑臨床決策支持、醫學影像分析和醫療流程優化的范式。本指南從計算可持續性、錯誤傳播控制、倫理安全防護和通用性擴展四大維度,系統解析醫療大模型落地落地的關鍵要…

代理模式深度解析

目錄 一 靜態代理 1.1 優點 1.2 缺點 1.3 適用場景 二 JDK動態代理 1 JDK動態代理的工作原理 1.1 創建代理類 1.2 加載代理類 1.3 實現方法調用 2. Proxy.newProxyInstance() 的核心工作流程 方法簽名 工作步驟 3. 代理類的生成與加載 3.1 代理類生成的關鍵方法 …

Spring Cache與Redis集成原理

一、核心架構圖解 #mermaid-svg-aiWGQLhmWx7kOfLz {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-aiWGQLhmWx7kOfLz .error-icon{fill:#552222;}#mermaid-svg-aiWGQLhmWx7kOfLz .error-text{fill:#552222;stroke:#5…

編程技能:調試02,設置斷點與刪除斷點

專欄導航 本節文章分別屬于《Win32 學習筆記》和《MFC 學習筆記》兩個專欄&#xff0c;故劃分為兩個專欄導航。讀者可以自行選擇前往哪個專欄。 &#xff08;一&#xff09;WIn32 專欄導航 上一篇&#xff1a;編程技能&#xff1a;調試01&#xff0c;調試介紹 回到目錄 下…

flink寫doris時的優化

1.概念 doris并不擅長高頻、小量數據的導入&#xff1b; 因為doris每一次數據導入都會在be節點上生成數據文件&#xff1b;如果高頻導入小量數據&#xff0c;就會在存儲層產生大量的小文件&#xff08;必然會影響到后續的查詢效率&#xff0c;也會對系統產生更多的compaction…

ElementNotInteractableException原因及解決辦法

在自動化測試中,ElementNotInteractableException是一個常見的異常,它通常發生在嘗試與網頁上的某個元素進行交互(例如點擊、輸入等操作)時,但由于該元素當前不可交互。這可能由多種原因引起,以下是一些常見的原因及其解決方法: 元素未完全加載 如果嘗試與頁面上的元素交…

如何從 GitHub 鏡像倉庫到極狐GitLab?

最近 GitHub 封禁中國用戶的事情鬧得沸沸揚揚,雖然官方發布的報道說中國用戶被限制登錄是因為配置錯誤導致,已經撤回了更新,中國用戶已經可以正常使用。但是這就像橫在國內開發者和企業頭上的“達摩克利斯之劍”。為了避免 GitHub 不可用而帶來的影響,國內開發者和企業可以…

服務器安裝nacos

1.下載依賴 docker pull nacos/nacos-server:v2.4.3安裝 docker run -d --name nacos-server -p 8848:8848 -e MODEstandalone nacos/nacos-server:v2.4.3把nacos中的data 文件和conf 文件copy到自己服務的文件夾 docker cp nacos-server:/home/nacos/data /home/admin1/…

Matter協議暗戰:蘋果、谷歌、亞馬遜的智能家居霸權爭奪

原文地址&#xff1a;Matter協議暗戰&#xff1a;蘋果、谷歌、亞馬遜的智能家居霸權爭奪 一、Matter 協議&#xff1a;巨頭聯手打造的 “智能家居聯合國” 1.1 從 CHIP 到 Matter&#xff1a;標準統一的十年長跑 智能家居發展多年&#xff0c;卻始終被 “孤島效應” 困擾。各…