Flutter消息编码插件standard_message_codec的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter消息编码插件standard_message_codec的使用

standard_message_codec 是Flutter SDK中用于高效编码和解码消息的二进制格式。与基于文本的格式(如JSON)不同,它不需要先解析为字符串再进行结构识别,而是直接操作字节数据,从而提高了效率。此外,它不需要预定义的模式或生成代码,这使得它非常适合动态消息,并且易于集成到现有代码库中。

Features

Efficiency

标准消息编解码是二进制格式,这意味着它避免了像JSON这样的文本格式所需的UTF8解码步骤。例如,考虑以下JSON片段:

{
    "data": [1, 2, 3, 4],
}

为了将此消息解码为Dart映射,必须首先将UTF8二进制文件解析并验证为Dart字符串。然后执行第二遍查找表示JSON结构的特定字符(例如"{" 和"}")。在解析过程中,不知道任何大小或长度,因此创建的结果Dart列表是在解码时逐渐追加的。

相比之下,解码标准消息编解码版本的消息避免了UTF8解码,而是直接在字节上操作。唯一构造的字符串将是"data"键。数据字段中的列表长度被编码在结构中,意味着可以分配正确长度的对象并在解码时填充。

Schemaless

使用standard_message_codec不需要模式(如protobuf)或任何生成的代码。这使得它非常容易用于动态消息,并简化了与现有代码库的集成。但是,这也意味着应用程序有责任验证发送/接收的消息结构。不像protobuf那样自动提供向后兼容性。

Getting Started

standard_message_codec可以在Flutter或纯Dart应用程序中用于编码和解码消息。下面是一个简单的示例,展示了如何使用它来编码一个消息:

import 'dart:typed_data';
import 'package:flutter/services.dart';

void main() {
  // Encoding a message
  final ByteData? encodedMessage =
      const StandardMessageCodec().encodeMessage(<Object, Object>{
    'foo': true,
    3: 'fizz',
  });
  print('The encoded message is $encodedMessage');

  // Decoding a message
  if (encodedMessage != null) {
    final Map<Object?, Object?>? decodedMessage =
        const StandardMessageCodec().decodeMessage(encodedMessage);
    print('The decoded message is $decodedMessage');
  }
}

这段代码首先创建了一个包含两个键值对的消息,然后使用StandardMessageCodec将其编码为ByteData对象。之后,它又演示了如何从编码后的ByteData对象中解码出原始的消息内容。

如果你想要更深入地了解或者查看更多的例子,你可以参考example/README.md,那里提供了更多关于如何在实际项目中使用standard_message_codec的信息。


更多关于Flutter消息编码插件standard_message_codec的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter消息编码插件standard_message_codec的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,standard_message_codec 是默认的消息编码插件,用于在 Flutter 和原生平台(如 Android 和 iOS)之间传递消息。它支持基本的数据类型,如字符串、数字、布尔值、列表、映射(字典)等。默认情况下,Flutter 的 MethodChannel 和 BasicMessageChannel 已经使用 standard_message_codec,因此你通常不需要显式地配置它。

以下是一个简单的示例,展示了如何在 Flutter 和原生平台之间使用默认的消息编码(即 standard_message_codec)传递消息。

Flutter 端代码

首先,创建一个 Flutter 插件通道,用于与原生平台通信。

import 'package:flutter/services.dart';

class MyAppChannel {
  static const MethodChannel _channel = MethodChannel('com.example.myapp/channel');

  // 从原生平台接收消息
  static Future<dynamic> receiveMessage() async {
    return _channel.invokeMethod('receiveMessage');
  }

  // 发送消息到原生平台
  static Future<void> sendMessage(String message) async {
    try {
      await _channel.invokeMethod('sendMessage', {'message': message});
    } on PlatformException catch (e) {
      print("Failed to send message: '${e.message}'.");
    }
  }
}

Android 端代码

在 Android 的 MainActivity 中设置 MethodChannel,以响应 Flutter 的消息。

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import android.os.Bundle;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "com.example.myapp/channel";

    @Override
    public void configureFlutterEngine(FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler(
                        (call, result) -> {
                            if (call.method.equals("sendMessage")) {
                                // 接收来自 Flutter 的消息
                                String message = call.argument("message");
                                // 在这里处理消息,比如打印到日志
                                android.util.Log.d("MyApp", "Received message from Flutter: " + message);

                                // 发送回复消息给 Flutter
                                result.success("Message received on Android");
                            } else if (call.method.equals("receiveMessage")) {
                                // 发送消息到 Flutter
                                result.success("Hello from Android");
                            } else {
                                result.notImplemented();
                            }
                        }
                );
    }
}

iOS 端代码

在 iOS 的 AppDelegate 中设置 MethodChannel,以响应 Flutter 的消息。

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(name: "com.example.myapp/channel", binaryMessenger: controller)
    
    channel.setMethodCallHandler({
      (call: FlutterMethodCall, result: @escaping FlutterResult) in
      if call.method == "sendMessage" {
        if let message = call.arguments as? Dictionary<String, String>, let msg = message["message"] {
          // 接收来自 Flutter 的消息
          print("Received message from Flutter: \(msg)")
          
          // 发送回复消息给 Flutter
          result(success: "Message received on iOS")
        } else {
          result(FlutterError(code: "INVALID_ARGUMENT", message: "Invalid argument", details: nil))
        }
      } else if call.method == "receiveMessage" {
        // 发送消息到 Flutter
        result(success: "Hello from iOS")
      } else {
        result(FlutterMethodNotImplemented)
      }
    })
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

使用示例

在 Flutter 端调用这些方法来测试通信:

void _sendMessage() async {
  await MyAppChannel.sendMessage("Hello from Flutter");
  final result = await MyAppChannel.receiveMessage();
  print("Received from native: $result");
}

在 Flutter 的 build 方法中添加一个按钮来触发消息发送:

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: Text('Flutter Message Codec Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _sendMessage,
          child: Text('Send Message'),
        ),
      ),
    ),
  );
}

这个示例展示了如何在 Flutter 和原生平台之间使用默认的 standard_message_codec 传递消息。注意,默认情况下,Flutter 的 MethodChannel 已经使用 standard_message_codec,因此你不需要显式地配置它。

回到顶部