马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
在 Flutter 跨平台开发中,Dart 层 与原生层(Android/iOS)的通讯是焦点需求之一。无论是调用摄像头、麦克风等装备硬件本领,获取体系信息,还是处理处罚高性能盘算任务,均需通过消息通道实现数据交互。Flutter提供了三种焦点消息通道,每种通道都有其独特的操持理念和实用场景。本文将具体剖析这三种通道,并联合音频处理处罚框架的操持,资助开发者深化对各通道使用场景的明白。
2 消息通道范例详解
Flutter 的消息通道本质上是 Dart 层与原生层(Platform Channel)之间的通讯桥梁,基于二进制流传输数据,通过编解码器(Codec)实现差别范例数据的序列化与反序列化。现在,Flutter重要提供了三种通道范例:BasicMessageChannel、MethodChannel 和 EventChannel。
2.1 BasicMessageChannel
BasicMessageChannel 用于Dart层与原生层之间的双向连续消息的传输,支持字符串、二进制、自界说对象等恣意范例数据交互,实用于需频仍数据交换的场景。它依靠MessageCodec举行数据编码 / 解码,默认使用支持底子范例、列表、映射的 StandardMessageCodec,也可自界说 StringCodec、BinaryCodec 等编解码器
下面以一个简单的从Flutter层发送音频数据到原生层,原生层再把音频数据转成文本再发送回Flutter的例子来表明其的使用:
Flutter 端(Dart)- import 'package:flutter/services.dart';
- // 初始化BasicMessageChannel,指定通道名称和编解码器
- final BasicMessageChannel _audioChannel = BasicMessageChannel(
- 'com.example.audio_channel', // 通道唯一标识
- StandardMessageCodec(), // 默认编解码器
- );
- // 发送音频数据到原生层
- void sendAudioData(Uint8List audioBytes) async {
- try {
- // 发送音频数据到原生层
- _audioChannel.send(audioBytes);
- } on PlatformException catch (e) {
- print('发送失败:${e.message}');
- }
- }
- // 监听原生层主动发送的消息(如转录的文本)
- void setupAudioChannelListener() {
- _audioChannel.setMessageHandler((message) async {
- if (message is String) {
- print('收到转录结果:$message');
- }
- return ''; // 可选:向原生层返回确认
- });
- }
复制代码 原生层(Android - Kotlin)- import io.flutter.plugin.common.BasicMessageChannel
- import io.flutter.plugin.common.StandardMessageCodec
- import io.flutter.embedding.engine.FlutterEngine
- class AudioMessageHandler(flutterEngine: FlutterEngine) {
- // 初始化通道,与Flutter端通道名称保持一致
- private val audioChannel: BasicMessageChannel<Any> = BasicMessageChannel(
- flutterEngine.dartExecutor.binaryMessenger,
- "com.example.audio_channel", // 名字
- StandardMessageCodec.INSTANCE
- )
- init {
- // 设置消息处理器,接收Flutter发送的音频数据
- audioChannel.setMessageHandler { message, reply ->
- if (message is ByteArray) {
- // 模拟音频转写处理
- transcribeAudio(message)
- // 向Flutter返回转录结果
- reply.reply('')
- }
- }
- }
- // 模拟原生层主动发送进度信息到Flutter
- private fun sendTranscribeProgress(asrResult: String) {
- audioChannel.send(asrResult)
- }
- // 模拟音频转写逻辑
- private fun transcribeAudio(audioBytes: ByteArray) {
- // 实际场景中调用原生音频转写SDK
- sendTranscribeProgress("转写结果:这是一段测试音频")
- }
- }
复制代码 原生层(iOS - Swift)- import Flutter
- class AudioMessageHandler: NSObject, FlutterPlugin {
- private let audioChannel: FlutterBasicMessageChannel
-
- init(messenger: FlutterBinaryMessenger) {
- // 初始化通道
- audioChannel = FlutterBasicMessageChannel(
- name: "com.example.audio_channel",
- messenger: messenger,
- codec: FlutterStandardMessageCodec.sharedInstance()
- )
- super.init()
- setupHandler()
- }
-
- private func setupHandler() {
- // 处理Flutter发送的音频数据
- audioChannel.setMessageHandler { [weak self] message, reply in
- guard let audioData = message as? Data else {
- reply(nil)
- return
- }
- // 模拟音频转写
- self?.transcribeAudio(audioData)
- reply("")
- }
- }
-
- // 发送转写进度到Flutter
- private func sendTranscribeProgress(asrResult: String) {
- audioChannel.sendMessage(asrResult)
- }
-
- // 模拟音频转写
- private func transcribeAudio(_ data: Data) {
- self?.sendTranscribeProgress("转写结果:这是一段测试音频")
- }
- }
复制代码 上面只是一个最简单的使用BasicMessageChannel的示例,在实际的应用过程中, BasicMessageChannel的name 和 codec 肯定要三个端都保持同等(Dart,Android,iOS)
别的,需留意一个实践细节:很多文档提及传输二进制数据时,使用 BinaryCodec 解码器服从最高,但实际测试发现,在 Android 平台中,BasicMessageChannel + BinaryCodec 存在特定 Bug—— 原生层发送至 Flutter 层的数据(无论原生层怎样处理处罚 ByteBuffer)始终为空(Flutter 层发送的数据可被原生层正常吸收剖析);干系讨论可参考 https://github.com/flutter/flutter/issues/19849
2.2 MethodChannel
MethodChannel 用于 Dart 层调用原生层方法(或原生层调用 Dart 层方法),支持同步与异步调用,实用于单次哀求 - 相应式交互场景。它接纳 “方法名 + 参数” 的通讯模式,Dart 层通过 invokeMethod 调用原生方法,原生层则通过 MethodCallHandler 处理处罚哀求并返回效果。
MethodChannel支持的数据范例包罗根本范例(boolean, int, double等)、字符串、列表和映射等,这些范例在消息中的序列化和反序列化会主动举行。同时,MethodChannel 具备全双工通讯本领:Flutter 可主动向原生端发送消息并吸收相应,原生端也可主动向 Flutter 端发送消息,待 Flutter 处理处罚后吸收返回效果。
简单的代码示例
Flutter 端(Dart)- import 'package:flutter/services.dart';
- // 初始化MethodChannel
- final MethodChannel _audioMethodChannel = MethodChannel('com.example.audio_method');
- // 调用原生层音频转写方法
- Future<String?> transcribeAudio(Uint8List audioBytes) async {
- try {
- // 调用原生方法“transcribe”,传入音频数据
- final result = await _audioMethodChannel.invokeMethod<String>(
- 'transcribe', // 方法名
- {'audioData': audioBytes}, // 参数(映射类型)
- );
- return result;
- } on PlatformException catch (e) {
- print('转写失败:${e.code} - ${e.message}');
- return null;
- }
- }
复制代码 原生层(Android - Kotlin)- import io.flutter.plugin.common.MethodChannel
- import io.flutter.embedding.engine.FlutterEngine
- class AudioMethodHandler(flutterEngine: FlutterEngine) {
- init {
- // 注册MethodChannel
- MethodChannel(
- flutterEngine.dartExecutor.binaryMessenger,
- "com.example.audio_method"
- ).setMethodCallHandler { call, result ->
- when (call.method) {
- "transcribe" -> {
- // 获取Flutter传入的音频数据
- val audioData = call.argument<ByteArray>("audioData")
- if (audioData == null) {
- result.error("INVALID_DATA", "音频数据为空", null)
- return@setMethodCallHandler
- }
- // 调用转写逻辑
- val transcript = transcribeAudio(audioData)
- result.success(transcript) // 返回结果
- }
- else -> {
- result.notImplemented() // 方法未实现
- }
- }
- }
- }
-
- private fun transcribeAudio(audioData: ByteArray): String {
- // 实际调用原生转写SDK
- return "转写结果:MethodChannel处理的音频"
- }
- }
复制代码 原生层(iOS - Swift)- import Flutter
- class AudioMethodHandler: NSObject, FlutterPlugin {
- static func register(with registrar: FlutterPluginRegistrar) {
- let channel = FlutterMethodChannel(
- name: "com.example.audio_method",
- binaryMessenger: registrar.messenger()
- )
- let instance = AudioMethodHandler()
- registrar.addMethodCallDelegate(instance, channel: channel)
- }
-
- func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
- switch call.method {
- case "transcribe":
- guard let args = call.arguments as? [String: Any],
- // 获取Flutter传入的音频数据
- let audioData = args["audioData"] as? Data else {
- result(FlutterError(code: "INVALID_DATA", message: "音频数据为空", details: nil))
- return
- }
- let transcript = transcribeAudio(audioData)
- result(transcript)
- default:
- result(FlutterMethodNotImplemented)
- }
- }
-
- private func transcribeAudio(_ data: Data) -> String {
- return "转写结果:MethodChannel处理的音频"
- }
- }
复制代码 2.3 EventChannel
EventChannel 专为连续的事故流或数据流畅讯而操持,重要用于原生层向Dart 层发送单向事故流(如传感器数据、实时日记).它的焦点逻辑是:原生层通过 EventSink 发送 “乐成”“错误”“竣事” 等范例的事故,Dart 层则通过 Stream 监听事故流,天然适配连续数据的吸收与处理处罚。
,原生层通过EventSink发送事故(乐成 / 错误 / 竣事),Dart 层通过Stream监听事故流。
EventChannel 尤其恰当处理处罚原平生台产生的连续数据,比方传感器(加快度、陀螺仪)的实时数据、GPS 位置更新、实时音频流等。需留意的是,它是单向通讯机制 —— 原生层可向 Flutter 端连续推送数据,但 Flutter 端无法通过同一通道向原生层回传数据。
简单的代码示例
Flutter 端(Dart)- import 'package:flutter/services.dart';
- // 初始化EventChannel
- final EventChannel _audioEventChannel = EventChannel('com.example.audio_events');
- // 监听原生层发送的转写事件流
- void listenToTranscribeEvents(Uint8List audioBytes) {
- // 获取事件流
- final stream = _audioEventChannel.receiveBroadcastStream(audioBytes);
-
- // 监听事件
- stream.listen(
- (event) {
- if (event is String) {
- print('收到转写片段:$event');
- } else if (event is double) {
- print('转写进度:${event * 100}%');
- }
- },
- onError: (error) {
- print('转写出错:$error');
- },
- onDone: () {
- print('转写完成');
- },
- );
- }
复制代码 原生层(Android - Kotlin)- import io.flutter.plugin.common.EventChannel
- import io.flutter.embedding.engine.FlutterEngine
- import kotlinx.coroutines.CoroutineScope
- import kotlinx.coroutines.Dispatchers
- import kotlinx.coroutines.delay
- import kotlinx.coroutines.launch
- class AudioEventHandler(flutterEngine: FlutterEngine) {
- private var eventSink: EventChannel.EventSink? = null
-
- init {
- // 注册EventChannel
- EventChannel(
- flutterEngine.dartExecutor.binaryMessenger,
- "com.example.audio_events"
- ).setStreamHandler(object : EventChannel.StreamHandler {
- // 当Dart层开始监听时调用
- override fun onListen(arguments: Any?, sink: EventChannel.EventSink) {
- eventSink = sink
- if (arguments is ByteArray) {
- // 开始处理音频并发送事件
- processAudioStream(arguments)
- } else {
- sink.error("INVALID_ARG", "参数不是音频数据", null)
- }
- }
-
- // 当Dart层取消监听时调用
- override fun onCancel(arguments: Any?) {
- eventSink = null
- // 释放资源(如停止转写任务)
- }
- })
- }
-
- // 模拟流式转写(分片段发送结果)
- private fun processAudioStream(audioData: ByteArray) {
- // 这里需要实际调用其他服务来获取最终的结果
- CoroutineScope(Dispatchers.IO).launch {
- // 发送进度
- eventSink?.success(0.3)
- delay(500)
- // 发送转写片段
- eventSink?.success("这是第一段转写文本")
- delay(500)
- eventSink?.success(0.7)
- delay(500)
- eventSink?.success("这是第二段转写文本")
- delay(500)
- eventSink?.success(1.0)
- // 结束流
- eventSink?.endOfStream()
- }
- }
- }
复制代码 原生层(iOS - Swift)- import Flutter
- import Foundation
- class AudioEventHandler: NSObject, FlutterStreamHandler {
- private var eventSink: FlutterEventSink?
- private var isProcessing = false
-
- static func register(with registrar: FlutterPluginRegistrar) {
- let channel = FlutterEventChannel(
- name: "com.example.audio_events",
- binaryMessenger: registrar.messenger()
- )
- let instance = AudioEventHandler()
- channel.setStreamHandler(instance)
- }
-
- // 开始监听
- func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
- self.eventSink = events
- guard let audioData = arguments as? Data else {
- events(FlutterError(code: "INVALID_ARG", message: "参数不是音频数据", details: nil))
- return nil
- }
- processAudioStream(audioData)
- return nil
- }
-
- // 取消监听
- func onCancel(withArguments arguments: Any?) -> FlutterError? {
- eventSink = nil
- isProcessing = false
- return nil
- }
-
- // 模拟流式转写
- private func processAudioStream(_ data: Data) {
- isProcessing = true
- let queue = DispatchQueue.global()
-
- // 发送进度和片段
- queue.asyncAfter(deadline: .now() + 0.5) { [weak self] in
- self?.eventSink?(0.3)
- }
- queue.asyncAfter(deadline: .now() + 1.0) { [weak self] in
- self?.eventSink?("这是第一段转写文本")
- }
- queue.asyncAfter(deadline: .now() + 1.5) { [weak self] in
- self?.eventSink?(0.7)
- }
- queue.asyncAfter(deadline: .now() + 2.0) { [weak self] in
- self?.eventSink?("这是第二段转写文本")
- }
- queue.asyncAfter(deadline: .now() + 2.5) { [weak self] in
- self?.eventSink?(1.0)
- self?.eventSink?(FlutterEndOfEventStream)
- }
- }
- }
复制代码 3 消息通道实用场景分析
在实际开发中,选择哪种范例的Channel取决于具体的通讯需求。明白每种Channel的特点和实用场景对于构建高效、可维护的Flutter应用至关告急。
通道范例焦点本领实用场景范例案例BasicMessageChannel双向连续消息通报频仍数据交互、实时同步音频/视频流传输、即时通讯消息交换MethodChannel单次方法调用(哀求-相应)调用原生API、获取单次效果装备信息获取、权限查抄、单次数据处理处罚EventChannel原生向Dart推送事故流连续数据推送、状态监听传感器数据(加快度、陀螺仪)、实时日记流场景选择发起:
- 假如须要双向频仍通讯(如Flutter与原生连续交换音频帧):优先选择BasicMessageChannel,其操持更轻量,恰当连续数据活动。
- 假如只须要单次调用并获取效果(如调用原生SDK完成一次音频转写):使用MethodChannel,代码更简便,符合“方法调用”的直觉。
- 假如须要原生主动推送连续数据(如实时语音转写的逐句效果):EventChannel是最佳选择,通过Stream可天然处理处罚流式数据。
4 音频处理处罚框架操持
前文已分析了Flutter三种消息通道的特点及其实用场景,本章节我们就联合这些特点来操持一个音频处理处罚框架,这个框架焦点功能为:“将音频数据转成文本消息”,这里重要有4个功能点:
- Flutter层负责把音频的二进制数据发送给原生层;
- 原生层在收到音频数据后,调用第三方的服务完成音频转文本;
- 原生层并把音频转出来的文本效果发送回Flutter层展示;
- Flutter 层触发 “开始、竣事、停息、继续” 等控制指令,原生层相应并处理处罚;
这4个功能点里,除了”原生层调用第三方服务转写音频“ 无需跨层交互外,其他的功能点都是均须要原生和Flutter层通过消息通道实现交互;
4.1 音频数据的传输
音频数据传输需重点思量三方面:Flutter 层数据流的管理、跨平台通道的选择与数据传输、原生层的数据吸收。
在Flutter层会通过StreamController来监听音频数据的厘革(实现数据流管理),监听到音频数据的厘革后,通过BasicMessageChannel通道(将音频数据)发送到原生层,而且由于传输的是二进制的数据,编码器接纳了BinaryCodec来直接传输 —— 这一通讯机制可制止不须要的数据复制与编码转换,最大化传输服从。- import 'dart:async';
- import 'dart:typed_data';
- import 'package:flutter/services.dart';
- class AudioTransferManager {
- // 定义BinaryCodec的BasicMessageChannel(名称需与原生层一致)
- static const BasicMessageChannel<ByteData> _audioChannel = BasicMessageChannel(
- 'com.example.audio_transfer/binary', // 通道唯一标识
- BinaryCodec(), // 直接传输二进制,避免额外编解码开销
- );
- // 管理音频数据流的控制器
- final StreamController<Uint8List> _audioStreamController = StreamController<Uint8List>.broadcast();
-
- // 音频数据流订阅对象(用于取消监听)
- StreamSubscription? _audioSubscription;
- // 初始化:启动音频采集并监听数据流
- void startAudioTransfer() {
- // 假设通过某个音频采集库获取原始音频流(如flutter_sound、audio_recorder等)
- Stream<Uint8List> audioStream = AudioRecorder.start(); // 伪代码:启动音频采集
-
- // 订阅音频流,实时发送数据到原生层
- _audioSubscription = audioStream.listen(
- (Uint8List audioData) {
- _sendAudioToNative(audioData);
- },
- onError: (error) {
- print('音频流错误: $error');
- },
- onDone: () {
- print('音频流结束');
- },
- );
- }
- // 发送音频二进制数据到原生层
- Future<void> _sendAudioToNative(Uint8List audioData) async {
- try {
- // 将Uint8List转换为ByteData(BinaryCodec要求的输入类型)
- final byteData = ByteData.view(audioData.buffer);
- // 发送数据(可根据需要等待原生层响应)
- await _audioChannel.send(byteData);
- } catch (e) {
- print('发送音频数据失败: $e');
- }
- }
- // 释放资源:停止传输并清理
- void stopAudioTransfer() {
- _audioSubscription?.cancel(); // 取消流订阅
- _audioStreamController.close(); // 关闭流控制器
- // 通知原生层停止处理(可选)
- _audioChannel.send(ByteData(0)); // 发送空数据作为停止信号
- }
- }
复制代码 原生层吸收(以Android为例):
- import io.flutter.embedding.engine.FlutterEngine
- import io.flutter.plugin.common.BasicMessageChannel
- import io.flutter.plugin.common.BinaryCodec
- import java.nio.ByteBuffer
- class AudioTransferHandler(flutterEngine: FlutterEngine) {
- init {
- // 注册与Flutter对应的BasicMessageChannel
- val channel = BasicMessageChannel(
- flutterEngine.dartExecutor.binaryMessenger,
- "com.example.audio_transfer/binary", // 与Flutter层通道名称一致
- BinaryCodec.INSTANCE
- )
- // 设置消息接收回调
- channel.setMessageHandler { message, reply ->
- // message为Flutter发送的ByteData,转换为字节数组
- val audioData = message?.array() // 二进制音频数据(uint8List对应byte[])
-
- if (audioData != null && audioData.isNotEmpty()) {
- // 处理音频数据(如写入文件、实时处理、转发等)
- processAudioData(audioData)
- } else {
- // 收到空数据,停止处理
- stopProcessing()
- }
-
- // 可选:向Flutter层发送响应(如确认接收)
- reply.reply(null)
- }
- }
- // 处理音频二进制数据
- private fun processAudioData(audioData: ByteArray) {
- // 示例:将音频数据写入缓冲区或调用第三方的服务,如azure,sonix,科大讯飞之类的
- // 注意:需在子线程处理,避免阻塞UI线程
- AudioProcessor.enqueue(audioData)
- }
- // 停止音频处理
- private fun stopProcessing() {
- AudioProcessor.clear()
- }
- }
复制代码 4.2 文本效果的传输
随着音频数据的连续输入,其转换后的文本信息需连续回传至 Flutter 层(原生→Flutter)。此处接纳 EventChannel 将文本传输回 Flutter 层(也可使用 BasicMessageChannel,只需选择符合的解码器),焦点通讯逻辑为:通过 EventChannel 实现原生层向 Flutter 层的单向数据推送。
原生层举行文本的推送:
- import io.flutter.plugin.common.EventChannel
- import io.flutter.plugin.common.PluginRegistry.Registrar
- class AudioTransferHandler(flutterEngine: FlutterEngine) {
- private val eventChannel: EventChannel
- private var eventSink: EventChannel.EventSink? = null
- init {
- // 初始化EventChannel
- eventChannel = EventChannel(
- flutterEngine.dartExecutor.binaryMessenger,
- "com.audio.text/result_channel"
- )
- eventChannel.setStreamHandler(object : EventChannel.StreamHandler {
- override fun onListen(arguments: Any?, sink: EventChannel.EventSink) {
- eventSink = sink
- // 初始化音频转文本处理器...
- }
- override fun onCancel(arguments: Any?) {
- eventSink = null
- // 释放资源...
- }
- })
- }
- // 推送文本结果到Flutter
- fun sendTextResult(text: String) {
- registrar.activity().runOnUiThread {
- eventSink?.success(text)
- }
- }
- // 其他音频处理逻辑...
- }
复制代码 Flutter层监听原生的推送:
- import 'dart:async';
- import 'package:flutter/services.dart';
- class AudioTransferManager {
- // 省略其他的代码
- // 文本结果回传的EventChannel
- static const EventChannel _textEventChannel = EventChannel(
- 'com.audio.text/result_channel',
- );
- // 文本结果流订阅
- StreamSubscription? _textSubscription;
- // 开始监听文本结果
- void startListening(void Function(String) onTextReceived) {
- _textSubscription = _textEventChannel.receiveBroadcastStream().listen(
- (data) {
- onTextReceived(data as String);
- },
- onError: (error) {
- // 错误处理...
- },
- );
- }
- // 停止监听并释放资源
- void stopListening() {
- _textSubscription?.cancel();
- }
- // 其他音频相关逻辑...
- }
复制代码 4.3 控制指令的传输
控制指令的交互雷同接口方法调用,需返回调用效果,因此接纳 MethodChannel 传输。该场景的通讯机制为:通过 MethodChannel 传输 “开始、停息” 等控制指令,同时吸收原生层返回的指令实验效果(如 “启动乐成”“已停息”)。
原生层的监听对应方法的调用:
- import io.flutter.embedding.engine.FlutterEngine
- import io.flutter.plugin.common.MethodCall
- import io.flutter.plugin.common.MethodChannel
- import io.flutter.plugin.common.MethodChannel.MethodCallHandler
- class AudioControlHandler(flutterEngine: FlutterEngine) : MethodCallHandler {
- init {
- // 注册MethodChannel
- MethodChannel(
- flutterEngine.dartExecutor.binaryMessenger,
- "com.audio.control/command"
- ).setMethodCallHandler(this)
- }
- // 处理Flutter层的方法调用
- override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
- when (call.method) {
- "start" -> {
- // 解析参数
- val sampleRate = call.argument<Int>("sampleRate") ?: 16000
- // 执行启动逻辑...
- val success = true // 实际处理结果
- result.success(success) // 返回结果给Flutter
- }
- "stop" -> {
- // 执行停止逻辑...
- result.success("stopped_successfully") // 返回字符串结果
- }
- // 这里可增加更多的控制方法,如pause,resume
- else -> {
- result.notImplemented() // 未实现的方法
- }
- }
- }
- // ... 其他原生处理逻辑
- }
复制代码 Flutter层的注册对应方法的调用:
- import 'package:flutter/services.dart';
- class AudioControlChannel {
- // 定义MethodChannel(通道名称需与原生层一致)
- static const MethodChannel _methodChannel = MethodChannel(
- 'com.audio.control/command',
- );
- // 发送控制指令并获取返回结果(示例:启动音频处理)
- Future<bool> startProcessing() async {
- try {
- // 调用原生方法,传入参数(可选)
- final result = await _methodChannel.invokeMethod<bool>(
- 'start', // 方法名
- {'sampleRate': 16000, 'channel': 1}, // 可选参数
- );
- return result ?? false;
- } on PlatformException catch (e) {
- print('控制指令调用失败: ${e.message}');
- return false;
- }
- }
- // 其他控制方法(示例:停止音频处理)
- Future<String> stopProcessing() async {
- final result = await _methodChannel.invokeMethod<String>('stop');
- return result ?? 'stopped';
- }
- // ... 其他控制指令方法(如暂停、配置参数等)
- }
复制代码 5 总结
本文 聚焦 Flutter 开发中 Dart 层与原生层的通讯需求,先先容了 BasicMessageChannel、MethodChannel、EventChannel 三种焦点消息通道,接着具体剖析各通道的焦点本领、具体代码示例及独特特点,随后分析它们的实用场景并给出选择发起,末了联合音频处理处罚框架的操持,举例分析各消息通道在实际开发中的应用(
- BasicMessageChannel:音频二进制数据传输(Flutter→原生)
- EventChannel:文本效果流推送(原生→Flutter)
- MethodChannel:控制指令调用与效果返回(双向,带返回值))
助力开发者明白其使用方式。
6 参考
|