[关闭]
@TryLoveCatch 2019-08-28T11:18:08.000000Z 字数 16882 阅读 1786

Flutter之Platform Channel

flutter


参考

Flutter如何和Native通信-Android视角
深入理解Flutter Platform Channel
底层原理 - 深入探索Platform Channel
Flutter Platform Channel 使用与源码分析

简介

Flutter是可以同时在iOS和Android系统上运行的,那么就有一个问题,Flutter如何和Native进行通信呢?。比如说,Flutter app要显示手机的电量,而电量只能通过平台的系统Api获取。这时就需要有个机制使得Flutter可以通过某种方式来调用这个系统Api并且获得返回值。那么Flutter是如何做到的呢?答案是Platform Channels

通过Platform Channels传递的消息都是异步的

Platform Channels

Flutter定义了三种不同类型的Channel,它们分别是:

重要概念

name

channel的名字,可以理解为id,就是独一无二的存在,flutter和native保持一致即可。

messager

消息信使,BinaryMessenger类型,BinaryMessenger是PlatformChannel与Flutter端的通信的工具,其通信使用的消息格式为二进制格式数据,BinaryMessenger在Android中是一个接口,它的实现类为FlutterNativeView。

codec

Codec是消息编解码器,主要用于将二进制格式的数据转化为Handler能够识别的数据,Flutter定义了两种Codec:MessageCodec和MethodCodec。MessageCodec用于二进制格式数据与基础数据之间的编解码,BasicMessageChannel所使用的编解码器是MessageCodec。MethodChannel和EventChannel所使用的编解码均为MethodCodec。

Handler

Flutter定义了三种类型的Handler,它们与PlatformChannel类型一一对应,分别是MessageHandler、MethodHandler、StreamHandler。在使用PlatformChannel时,会为它注册一个Handler,PlatformChannel会将该二进制数据通过Codec解码为转化为Handler能够识别的数据,并交给Handler处理。当Handler处理完消息之后,会通过回调函数返回result,将result通过编解码器编码为二进制格式数据,通过BinaryMessenger发送回Flutter端。

BinaryMessenger

  1. public interface BinaryMessenger {
  2. void send(String channel, ByteBuffer message);
  3. void send(String channel, ByteBuffer message, BinaryReply callback);
  4. void setMessageHandler(String channel, BinaryMessageHandler handler);
  5. interface BinaryMessageHandler {
  6. void onMessage(ByteBuffer message, BinaryReply reply);
  7. }
  8. interface BinaryReply {
  9. void reply(ByteBuffer reply);
  10. }
  11. }

Codec

消息编解码器Codec主要用于将二进制格式的数据转化为Handler能够识别的数据,Flutter定义了两种Codec:MessageCodec和MethodCodec。

MessageCodec

MessageCodec用于二进制格式数据与基础数据之间的编解码。BasicMessageChannel所使用的编解码器就是MessageCodec。

Android中,MessageCodec是一个接口,定义了两个方法:

  1. public interface MessageCodec<T> {
  2. ByteBuffer encodeMessage(T message);
  3. T decodeMessage(ByteBuffer message);
  4. }

MessageCodec有多个不同的实现:

BinaryCodec

原封不动的返回二进制数据,可以使传递内存数据块时在编解码阶段免于内存拷贝。Android中为ByteBuffer

StringCodec

字符串与二进制数据之间的编解码,其编码格式为UTF-8

JSONMessageCodec

基础数据与二进制数据之间的编解码,其支持基础数据类型以及列表、字典。

StandardMessageCodec

BasicMessageChannel的默认编解码器,其支持基础数据类型、二进制数据、列表、字典。

MethodCodec

MethodCodec用于二进制数据与方法调用(MethodCall)和返回结果之间的编解码。MethodChannel和EventChannel所使用的编解码器均为MethodCodec。

MethodCodec用于MethodCall对象的编解码,一个MethodCall对象代表一次从Flutter端发起的方法调用。

  1. public interface MethodCodec {
  2. Object decodeEnvelope(ByteBuffer envelope)
  3. MethodCall decodeMethodCall(ByteBuffer methodCall)
  4. ByteBuffer encodeErrorEnvelope(String errorCode, String errorMessage, Object errorDetails)
  5. ByteBuffer encodeMethodCall(MethodCall methodCall)
  6. ByteBuffer encodeSuccessEnvelope(Object result)
  7. }

MethodCall有2个成员变量:

  1. public interface MethodCall {
  2. Object arguments
  3. String method
  4. }

由于处理的是方法调用,故相比于MessageCodec,MethodCodec多了对调用结果的处理。

MethodCodec有两种实现:

JSONMethodCodec

JSONMethodCodec的编解码依赖于JSONMessageCodec,当其在编码MethodCall时,会先将MethodCall转化为字典{"method":method,"args":args}。其在编码调用结果时,会将其转化为一个数组,调用成功为[result],调用失败为[code,message,detail]。再使用JSONMessageCodec将字典或数组转化为二进制数据。
比如当前想要调用某个Channel的setVolum(5),其对应的MethodCall被被转成{"method":"setVolum","args":{"volum":5}}

StandardMethodCodec

MethodCodec的默认实现,StandardMethodCodec的编解码依赖于StandardMessageCodec,当其编码MethodCall时,会将method和args依次使用StandardMessageCodec编码,写入二进制数据容器。其在编码方法的调用结果时,若调用成功,会先向二进制数据容器写入数值0(代表调用成功),再写入StandardMessageCodec编码后的result。而调用失败,则先向容器写入数据1(代表调用失败),再依次写入StandardMessageCodec编码后的code,message和detail。

总结

- Codec Desc
MessageCodec StandardMessageCodec 支持基础数据格式与二进制之间的转换,包括 Boolean 、Number、String、Byte、List、Map、数组等。
BinaryCodec 支持二进制数据的直接传递,实际上是没有做任何编解码,可以通过它做大内存块的数据传递。
StringCodec 支持字符串(UTF-8)与二进制之间的转换。
JSONMessageCodec 支持把数据转换为JSON,再调用 StringCodec 的编解码。
MethodCodec StandardMethodCodec 调用 StandardMessageCodec 传递方法的名字和参数。
JSONMethodCodec 调用 JSONMessageCodec 传递方法的名字和参数。

Handler

当我们接收二进制格式消息并使用Codec将其解码为Handler能处理的消息后,就该Handler上场了。
Flutter定义了三种类型的Handler,与Channel类型一一对应。

我们向Channel注册一个Handler时,实际上就是向BinaryMessager注册一个与之对应的BinaryMessageHandler。当消息派分到BinaryMessageHandler后,Channel会通过Codec将消息解码,并传递给Handler处理。

MessageHandler

MessageHandler用户处理字符串或者半结构化的消息,其onMessage方法接收一个T类型的消息,并异步返回一个相同类型result。

  1. public static interface BasicMessageChannel.MessageHandler<T> {
  2. void onMessage(T message, BasicMessageChannel.Reply<T> reply)
  3. }

MethodHandler

MethodHandler用于处理方法的调用,其onMessageCall方法接收一个MethodCall类型消息,并根据MethodCall的成员变量method去调用对应的API,当处理完成后,根据方法调用成功或失败,通过Result返回对应的结果。

  1. public static interface MethodChannel.MethodCallHandler {
  2. void onMethodCall(MethodCall call, MethodChannel.Result result)
  3. }

StreamHandler

StreamHandler与前两者稍显不同,用于事件流的通信,最为常见的用途就是Platform端向Flutter端发送事件消息。当我们实现一个StreamHandler时,需要实现其onListen和onCancel方法。而在onListen方法的入参中,有一个EventSink(其在Android是一个对象,iOS端则是一个block)。我们持有EventSink后,即可通过EventSink向Flutter端发送事件消息。

  1. public static interface EventChannel.StreamHandler {
  2. void onCancel(Object arguments)
  3. void onListen(Object arguments, EventChannel.EventSink events)
  4. }
  5. public static interface EventChannel.EventSink {
  6. void endOfStream()
  7. void error(String errorCode, String errorMessage, Object errorDetails)
  8. void success(Object event)
  9. }

总结

-- name messager codec handler
BasicMessageChannel MessageCodec-StandardMessageCodec MessageHandler
MethodChannel MethodCodec-StandardMethodCodec MethodHandler
EventChannel MethodCodec-StandardMethodCodec StreamHandler

栗子

MethodChannel

Dart 调用 Android 方法

Dart代码:

  1. 第一步
  2. static const methodChannel = MethodChannel("method_channel_sample");
  3. 第二步
  4. Future<dynamic> getUserInfo(String method, {String userName}) async {
  5. return await methodChannel.invokeMethod(method, userName);
  6. }
  7. 第三步
  8. MaterialButton(
  9. color: Colors.blue,
  10. textColor: Colors.white,
  11. child: new Text('获取 snow 用户信息'),
  12. onPressed: () {
  13. getUserInfo("getInfo", userName: "snow")
  14. ..then((result) {
  15. setState(() {
  16. messageFromNative = result;
  17. });
  18. });
  19. },
  20. ),

Android代码:

  1. private void addMethodChannel() {
  2. mMethodChannel = new MethodChannel(getFlutterView(), "method_channel_sample");
  3. mMethodChannel.setMethodCallHandler((methodCall, result) -> {
  4. String method = methodCall.method;
  5. if ("getInfo".equals(method)) {
  6. String userName = (String) methodCall.arguments;
  7. if (userName.equals("rocx")) {
  8. String user = "name:rocx, age:18";
  9. result.success(user);
  10. } else {
  11. result.success("user not found");
  12. invokeSayHelloMethod();
  13. }
  14. }
  15. });
  16. }

Dart 调用 Android 代码分三步。

  • 首先在 Dart 端定义 MethodChannel 名字为 method_channel_sample。
  • 然后定义getUserInfo方法,传入要调用的方法名和参数。
  • 最后点击按钮执行方法,获取用户信息。

在 Android 端定一个 MethodChannel 名字和 Dart 端保持一致。设置 MethodCallHandler。当调用的是getInfo方法时,根据参数返回信息。

Android 调用 Dart 方法

Android代码:

  1. private void invokeSayHelloMethod() {
  2. mMethodChannel.invokeMethod("sayHello", "", new MethodChannel.Result() {
  3. @Override
  4. public void success(Object o) {
  5. Toast.makeText(MainActivity.this, o.toString(), Toast.LENGTH_LONG).show();
  6. }
  7. @Override
  8. public void error(String s, String s1, Object o) {
  9. }
  10. @Override
  11. public void notImplemented() {
  12. }
  13. });
  14. }

dart端代码:

  1. Future<dynamic> addHandler(MethodCall call) async {
  2. switch (call.method) {
  3. case "sayHello":
  4. return "Hello from Flutter";
  5. break;
  6. }
  7. }
  8. @override
  9. void initState() {
  10. super.initState();
  11. methodChannel.setMethodCallHandler(addHandler);
  12. }

在 Dart 端设置 MethodCallHandler 然后在 Android 端调用即可

BasicMessageChannel

Dart 向 Android 发送消息

dart端代码:

  1. 第一步
  2. static const basicMessageChannel = BasicMessageChannel(
  3. "basic_message_channel_sample", StandardMessageCodec());
  4. 第二步
  5. Future<dynamic> sayHelloToNative(String message) async {
  6. String reply = await basicMessageChannel.send(message);
  7. setState(() {
  8. msgReplyFromNative = reply;
  9. });
  10. return reply;
  11. }
  12. 第三步
  13. MaterialButton(
  14. color: Colors.blue,
  15. textColor: Colors.white,
  16. child: new Text('say hello to native'),
  17. onPressed: () {
  18. sayHelloToNative("hello");
  19. },
  20. ),

Android端代码:

  1. private void addBasicMessageChannel() {
  2. mBasicMessageChannel = new BasicMessageChannel<>(getFlutterView(), "basic_message_channel_sample", StandardMessageCodec.INSTANCE);
  3. mBasicMessageChannel.setMessageHandler((object, reply) -> {
  4. reply.reply("receive " + object.toString() + " from flutter");
  5. mBasicMessageChannel.send("native say hello to flutter");
  6. });
  7. }

Dart 向 Android 发送消息依然分为三步。

  • 首先在 Dart 端定义 BasicMessageChannel 名字为 basic_message_channel_sample。
  • 然后定义发送消息的方法sayHelloToNative。
  • 最后点击按钮向 Android 端发送消息。

在 Android 端定一个 BasicMessageChannel 名字和 Dart 端保持一致。设置 MethodCallHandler。当收到消息时发一个回复。

Android 向 Dart 发送消息

Android端代码:

  1. mBasicMessageChannel.send("native say hello to flutter");

dart端代码:

  1. Future<dynamic> addHandler(Object result) async {
  2. setState(() {
  3. msgReceiveFromNative = result.toString();
  4. });
  5. }
  6. void addMessageListener() {
  7. basicMessageChannel.setMessageHandler(addHandler);
  8. }
  9. @override
  10. void initState() {
  11. super.initState();
  12. addMessageListener();
  13. }

在 Dart 端设置 MessageHandler 然后在 Android 端直接发送消息即可。

EventChannel

dart端代码:

  1. 第一步
  2. static const eventChannel = EventChannel("event_channel_sample");
  3. void _onEvent(Object event) {
  4. setState(() {
  5. if (_streamSubscription != null) {
  6. eventMessage = event.toString();
  7. }
  8. });
  9. }
  10. void _onError(Object error) {
  11. setState(() {
  12. if (_streamSubscription != null) {
  13. eventMessage = "error";
  14. }
  15. });
  16. }
  17. @override
  18. void initState() {
  19. super.initState();
  20. eventMessage = "";
  21. 第二步
  22. _streamSubscription = eventChannel
  23. .receiveBroadcastStream()
  24. .listen(_onEvent, onError: _onError);
  25. }

Android端代码:

  1. private void addEventChannel() {
  2. mEventChannel = new EventChannel(getFlutterView(), "event_channel_sample");
  3. mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
  4. @Override
  5. public void onListen(Object o, EventChannel.EventSink eventSink) {
  6. task = new TimerTask() {
  7. @Override
  8. public void run() {
  9. runOnUiThread(() -> eventSink.success("i miss you " + System.currentTimeMillis()));
  10. }
  11. };
  12. timer = new Timer();
  13. timer.schedule(task, 2000, 3000);
  14. }
  15. @Override
  16. public void onCancel(Object o) {
  17. task.cancel();
  18. timer.cancel();
  19. task = null;
  20. timer = null;
  21. }
  22. });
  23. }

Dart 接受 Android stream event。

  • 首先在 Dart 端定义 EventChannel 名字为 event_channel_sample。
  • 然后设置receiveBroadcastStream监听,当 Android 端有消息发过来会回调_onEvent方法。

在 Android 端启动一个定时器,每隔3s向 Dart 端发送一次消息。

总结

如下图,在 Dart 与 Platform 通信过程中,通过 channel name 找到对方,然后把消息通过 codec 进行编解码,最后通过 binaryMessenger 进行发送。

底层机制

我们来说一下流程:

  • 当我们初始化一个Channel,也就是new的时候,会传入name,这个name就是这个channel的唯一标示。
  • 当我们向该Channel注册处理消息的Handler时,实际上会生成一个BinaryMessageHandler,并以channel name为key,注册到BinaryMessenger中。也就是说一个channel,有一个唯一标示的name,有一个与之对应的BinaryMessageHandler。
  • 当Flutter端发送消息到BinaryMessenger时,BinaryMessenger会根据其入参channel找到与之对应的BinaryMessageHandler,并交由其处理。
  • Binarymessenger并不知道Channel的存在,它只和BinaryMessageHandler打交道。而Channel和BinaryMessageHandler则是一一对应的。
  • 由于Channel从BinaryMessageHandler接收到的消息是二进制格式数据,无法直接使用,故Channel会将该二进制消息通过Codec(消息编解码器)解码为能识别的消息并传递给Handler进行处理。
  • 当Handler处理完消息之后,会通过回调函数返回result,并将result通过编解码器编码为二进制格式数据,通过BinaryMessenger发送回Flutter端。

有没有觉得根Binder很像?我们来简化一下:

Android侧:

Futter侧:

Android侧:

我们以MethodChannel为例,先来看使用:

  1. // Dart层
  2. static const methodChannel = MethodChannel("method_channel_sample");
  3. Future<dynamic> getUserInfo() async {
  4. return await methodChannel.invokeMethod("getInfo", {userName: "snow"});
  5. }
  6. =======================================================
  7. // Andrid层
  8. private void addMethodChannel() {
  9. mMethodChannel = new MethodChannel(getFlutterView(), "method_channel_sample");
  10. mMethodChannel.setMethodCallHandler((methodCall, result) -> {
  11. String method = methodCall.method;
  12. if ("getInfo".equals(method)) {
  13. String userName = (String) methodCall.arguments;
  14. if (userName.equals("rocx")) {
  15. String user = "name:rocx, age:18";
  16. result.success(user);
  17. } else {
  18. result.success("user not found");
  19. invokeSayHelloMethod();
  20. }
  21. }
  22. });
  23. }

这是一个简单的Dart调用Android的

  1. class MethodChannel {
  2. // 构造方法,通常我们只需要指定该channel的name,
  3. const MethodChannel(this.name, [this.codec = const StandardMethodCodec()]);
  4. // name作为通道的唯一标志付,用于区分不同的通道调用
  5. final String name;
  6. // 用于方法调用过程的编码
  7. final MethodCodec codec;
  8. // 用于发起异步平台方法调用,需要指定方法名,以及可选方法参数
  9. Future<dynamic> invokeMethod(String method, [dynamic arguments]) async {
  10. assert(method != null);
  11. // 将一次方法调用中需要的方法名和方法参数封装为MethodCall对象,然后使用MethodCodec对该
  12. // 对象进行进行编码操作,最后通过BinaryMessages中的send方法发起调用
  13. final dynamic result = await BinaryMessages.send(
  14. name,
  15. codec.encodeMethodCall(MethodCall(method, arguments)),
  16. );
  17. if (result == null)
  18. throw MissingPluginException('No implementation found for method $method on channel $name');
  19. return codec.decodeEnvelope(result);
  20. }
  21. }

一般来说,我们会创建MethodChannel对后,调用其invokeMethod()方法用于向平台发起一次调用
在invokeMethod()方法中会将一次方法调中的方法名method和方法参数arguments封装为MethodCall对象
然后使用MethodCodec对其进行二进制编码
最后通过Dart层的BinaryMessages的send()发起平台方法调用请求

  1. class BinaryMessages {
  2. ......
  3. static Future<ByteData> send(String channel, ByteData message) {
  4. final _MessageHandler handler = _mockHandlers[channel];
  5. // 在没有设置Mock Handler的情况下,继续调用_sendPlatformMessage()
  6. if (handler != null)
  7. return handler(message);
  8. return _sendPlatformMessage(channel, message);
  9. }
  10. static Future<ByteData> _sendPlatformMessage(String channel, ByteData message) {
  11. final Completer<ByteData> completer = Completer<ByteData>();
  12. ui.window.sendPlatformMessage(channel, message, (ByteData reply) {
  13. try {
  14. completer.complete(reply);
  15. } catch (exception, stack) {
  16. FlutterError.reportError(FlutterErrorDetails(
  17. exception: exception,
  18. stack: stack,
  19. library: 'services library',
  20. context: 'during a platform message response callback',
  21. ));
  22. }
  23. });
  24. return completer.future;
  25. }
  26. ......
  27. }

Dart层的BinaryMessages类中提供了用于发送和接受平台插件的二进制消息.最终会调用ui.window.sendPlatformMessage().
然后,会通过一系列的JNI方法,最后调用到Android层的BinaryMessenger里面的handleMessageFromDart(),而FlutterNativeView就是一个BinaryMessenger,所以它内部包含了一个Map,channel name和BinaryMessageHandler的对应关系

  1. public class FlutterNativeView implements BinaryMessenger {
  2. private final Map<String, BinaryMessageHandler> mMessageHandlers;
  3. ......
  4. private final class PlatformMessageHandlerImpl implements PlatformMessageHandler {
  5. // Called by native to send us a platform message.
  6. public void handleMessageFromDart(final String channel, byte[] message, final int replyId) {
  7. // 1.根据channel名称获取对应的BinaryMessageHandler对象.每个Channel对应一个
  8. // Handler对象
  9. BinaryMessageHandler handler = mMessageHandlers.get(channel);
  10. if (handler != null) {
  11. try {
  12. // 2.将字节数组对象封装为ByteBuffer对象
  13. final ByteBuffer buffer = (message == null ? null : ByteBuffer.wrap(message));
  14. // 3.调用handler对象的onMessage()方法来分发消息
  15. handler.onMessage(buffer, new BinaryReply() {
  16. private final AtomicBoolean done = new AtomicBoolean(false);
  17. @Override
  18. public void reply(ByteBuffer reply) {
  19. // 4.根据reply的情况,调用FlutterJNI中invokePlatformMessageXXX()方法将响应数据发送给Flutter层
  20. if (reply == null) {
  21. mFlutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
  22. } else {
  23. mFlutterJNI.invokePlatformMessageResponseCallback(replyId, reply, reply.position());
  24. }
  25. }
  26. });
  27. } catch (Exception exception) {
  28. mFlutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
  29. }
  30. return;
  31. }
  32. mFlutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
  33. }
  34. }

首先根据Channel名称从mMessageHandlers取出对应的二进制消息处理器BinaryMessageHandler
然后将字节数组message封装为ByteBuffer对象
然后调用BinaryMessageHandler实例的onMessage()方法处理ByteBuffer,并进行响应.

我们接下来看一下BinaryMessageHandler的onMessage()方法

  1. public final class MethodChannel {
  2. private final BinaryMessenger messenger;
  3. private final String name;
  4. private final MethodCodec codec;
  5. ......
  6. public void setMethodCallHandler(final @Nullable MethodCallHandler handler) {
  7. messenger.setMessageHandler(name,
  8. handler == null ? null : new IncomingMethodCallHandler(handler));
  9. }
  10. public interface Result {
  11. void success(@Nullable Object result);
  12. void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails);
  13. void notImplemented();
  14. }
  15. public interface MethodCallHandler {
  16. void onMethodCall(MethodCall call, Result result);
  17. }
  18. private final class IncomingMethodCallHandler implements BinaryMessageHandler {
  19. private final MethodCallHandler handler;
  20. IncomingMethodCallHandler(MethodCallHandler handler) {
  21. this.handler = handler;
  22. }
  23. @Override
  24. public void onMessage(ByteBuffer message, final BinaryReply reply) {
  25. // 1.使用codec对来自Flutter方法调用数据进行解码,并将其封装为MethodCall对象.
  26. // MethodCall中包含两部分数据:method表示要调用的方法;arguments表示方法所需参数
  27. final MethodCall call = codec.decodeMethodCall(message);
  28. try {
  29. // 2.调用自定义MethodCallHandler中的onMethodCall方法继续处理方法调用
  30. handler.onMethodCall(call, new Result() {
  31. @Override
  32. public void success(Object result) {
  33. // 调用成功时,需要回传数据给Flutter层时,使用codec对回传数据result
  34. // 进行编码
  35. reply.reply(codec.encodeSuccessEnvelope(result));
  36. }
  37. @Override
  38. public void error(String errorCode, String errorMessage, Object errorDetails) {
  39. // 调用失败时,需要回传错误数据给Flutter层时,使用codec对errorCode,
  40. // errorMessage,errorDetails进行编码
  41. reply.reply(codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails));
  42. }
  43. @Override
  44. public void notImplemented() {
  45. // 方法没有实现时,调用该方法后,flutter将会受到相应的错误消息
  46. reply.reply(null);
  47. }
  48. });
  49. } catch (RuntimeException e) {
  50. Log.e(TAG + name, "Failed to handle method call", e);
  51. reply.reply(codec.encodeErrorEnvelope("error", e.getMessage(), null));
  52. }
  53. }
  54. }
  55. }

首先使用codec对来自Flutter层的二进制数据进行解码,并将其封装为MethodCall对象
然后调用MethodCallHandler的onMethodCall()方法.

接下来就是handler的处理,这个是我们自己的逻辑了:

  1. mMethodChannel.setMethodCallHandler((methodCall, result) -> {
  2. String method = methodCall.method;
  3. if ("getInfo".equals(method)) {
  4. String userName = (String) methodCall.arguments;
  5. if (userName.equals("rocx")) {
  6. String user = "name:rocx, age:18";
  7. result.success(user);
  8. } else {
  9. result.success("user not found");
  10. invokeSayHelloMethod();
  11. }
  12. }
  13. });

我们会返回一个字符串给Dart

Dart层 --> MethodChannel.invokeMethod() --> codec编码MethodCall,包含方法名和参数 --> BinaryMessages.send() --> JNI --> Android层 --> BinaryMessage.handleMessageFromDart() --> BinaryMessageHandler.onMessage() 解码MethodCall,拿到方法名和参数 --> Handler.onMethodCall() --> 调用方法,返回结果 --> BinaryMessageHandler 编码结果二进制 --> BinaryMessage --> JNI --> Dart层

google_maps_flutter

在Flutter中嵌入Native组件的正确姿势

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注