Flutter 是跨平台应用程序的理想工具。您可以轻松地制作出具有颤动的表演剂和美丽的应用程序。但是,为了访问本机平台API,您需要与本机平台进行通信。 Flutter只能理解DART语言,而本地平台只能理解其各自的编程语言。那么,颤动和本地平台如何相互通信?它必须是扑朔迷离和本机平台的语言。那么,用来互相交流的是什么?
猜测
如果您猜到了,二进制,那么您猜对了。
Flutter通过传递二进制消息与本机平台进行对话。为了区分消息,使用了频道。那么我们如何通过平台发送这些二进制消息?
我们可以利用BinaryMessenger类在平台上发送消息。
BinaryMessenger类是Flutter团队定义的Messenger类,它在整个Flutter Platform屏障上发送二进制数据。该课程还注册了传入消息的处理程序。
下面的代码使用binarymessenger通过频道向平台发送二进制消息。
import 'dart:convert';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;
class CustomBinaryMessenger {
// A static method for sending a given value as a binary message.
static Future<void> givenValue(String data) async {
// Create a buffer to hold the binary data.
final WriteBuffer buffer = WriteBuffer();
// Convert the given data string into UTF-8 bytes.
final List<int> utf8Bytes = utf8.encode(data);
// Convert the UTF-8 bytes into an Uint8List.
final Uint8List utf8Int8List = Uint8List.fromList(utf8Bytes);
// Put the Uint8List into the buffer.
buffer.putUint8List(utf8Int8List);
// Get the final binary message data from the buffer.
final ByteData message = buffer.done();
// Send the binary message using the 'Messenger' class through chaneel `foo`.
await Messenger().send('foo', message);
return;
}
}
// A custom implementation of the BinaryMessenger interface. I am only handling
// send here for the sake of example
class Messenger implements BinaryMessenger {
@override
// Handle incoming platform messages. In this case, it throws an unsupported error.
Future<void> handlePlatformMessage(
String channel, ByteData? data, PlatformMessageResponseCallback? callback) {
throw UnsupportedError("This platform message handling is not supported.");
}
@override
// Send a binary message to the platform using the 'ui.PlatformDispatcher'.
Future<ByteData?>? send(String channel, ByteData? message) {
// Use the 'ui.PlatformDispatcher' to send the platform message and handle the callback
ui.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (data) {});
return null;
}
@override
// Set a handler for incoming messages. In this case, it throws an unsupported error.
void setMessageHandler(String channel, MessageHandler? handler) {
throw UnsupportedError("Setting message handler is not supported.");
}
}
现在在Android上,您可以使用以下代码接收:
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// Configure the binary messenger to handle messages from Flutter.
flutterEngine.dartExecutor.binaryMessenger.setMessageHandler("foo") { message, reply ->
message?.order(ByteOrder.nativeOrder()) // Ensure proper byte order.
val data = decodeUtf8String(message!!) // Decode the binary data to UTF-8 string.
val x = message.toString() // Convert the message to a string for demonstration.
// Display a Toast with the received message.
Toast.makeText(this, "Received message from Flutter: $data", Toast.LENGTH_SHORT).show()
reply.reply(null)
}
// Call the super method to finalize the FlutterEngine configuration.
super.configureFlutterEngine(flutterEngine)
}
// Function to decode a ByteBuffer into a UTF-8 string.
private fun decodeUtf8String(byteBuffer: ByteBuffer): String {
return try {
val byteArray = ByteArray(byteBuffer.remaining())
byteBuffer.get(byteArray)
String(byteArray, Charsets.UTF_8)
} catch (e: Exception) {
e.printStackTrace()
""
}
}
}
类似于iOS,
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let flutterViewController = self.window.rootViewController as! FlutterViewController
// Configure the binary messenger to handle messages from Flutter.
let binaryMessenger = flutterViewController.engine!.binaryMessenger
binaryMessenger.setMessageHandlerOnChannel("foo", binaryMessageHandler: { [weak self] message, reply in
// Ensure proper byte order.
guard let message = message else {
reply(nil)
return
}
// Decode the binary data to UTF-8 string.
if let data = String(data: message, encoding: .utf8) {
let x = message.debugDescription // Convert the message to a string for demonstration.
// Display an alert with the received message.
let alertController = UIAlertController(
title: "Message from Flutter",
message: data,
preferredStyle: .alert
)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
flutterViewController.present(alertController, animated: true, completion: nil)
}
reply(nil)
}
)
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// Function to decode a ByteBuffer into a UTF-8 string.
private func decodeUtf8String(byteBuffer: FlutterStandardTypedData) -> String? {
let byteArray = [UInt8](byteBuffer.data)
return String(bytes: byteArray, encoding: .utf8)
}
}
交流是双向的,您可以从本机平台发送到扑朔迷离。确保在我们的类Messenger
中实现setMessageHandler
,以从本机平台接收二进制消息并解码它们。只需扭转我们的代码流,您就可以发送:
在iOS中,使用
// Send a binary message from platform to the flutter. It takes channel and message
// as params
flutterViewController.engine!.binaryMessenger.send(onChannel: <#T##String#>, message: <#T##Data?#>)
在Android中,使用
// Send a binary message from platform to the flutter.It takes channel and message
// as params
flutterEngine.dartExecutor.binaryMessenger.send()
消息和响应是异步传递的,以确保用户界面保持响应能力。
现在,您可以将消息从颤动传递到本机平台,反之亦然。但是,如您所见,我们必须担心编码,解码和处理寄存器等。它可以导致详细代码并增加代码的复杂性。那么,解决方案是什么?
平台频道:使上述过程更容易导致平台频道。平台频道是结合频道名称和编解码器的构造。这种配对使消息可以转换为二进制格式,以进行传输,并在接收时促进其从二进制格式的转换。它使使用本机平台的工作变得更加容易。
查看一个名为MethodChannel的平台频道。如果您查看代码,可以看到它处理自己的binarymessenger。
在我的下一篇文章中,我们将查看平台频道,以及如何使用它将消息从颤音传递到本机平台,反之亦然。
保持好奇心,不要错过下一篇文章。