一、三种Channel
Flutter中通过Platform Channel实现Flutter和原生端的数据传递,那么这些数据是怎么传递的,传递的过程都做了哪些操作
Flutter定义了三种不同类型的Channel,分别是
-
BasicMessageChannel:用于传递字符串和半结构化的数据;
-
MethodChannel:用于传递方法调用;
-
EventChannel:用于数据流的通信;
官方大图:
二、MethodChannel实现原理
-
从android端分析MethodChannel的实现原理,入口选在使用MethodChannel的使用的地方是最合适的。
2.1、MethodChannel如何使用
从Android端的角度来看:
//1、注册通道
MethodChannel channel = new MethodChannel(getFlutterView(),"flutter/channel");
//2、设置回调,被call回调
channel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
//3、主动call flutter的方法
channel.invokeMethod("callFlutter", "params", new MethodChannel.Result() {
@Override
public void success(Object result) {
//call success
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
//call fail
@Override
public void notImplemented() {
//flutter没有对应的实现方法
2.2、源码分析
2.2.1、MethodChannel的构造函数
public MethodChannel(BinaryMessenger messenger, String name) {
this(messenger, name, StandardMethodCodec.INSTANCE);
- 入参是一个通讯BinaryMessenger, 专门和Flutter进行通信的一个二进制异步消息接口;
- 使用的时候通常是传入一个FlutterView,因为FlutterView实现了这个接口。
2.2.2、Android到Flutter消息发送过程
public void invokeMethod(String method, @Nullable Object arguments, Result callback) {
messenger.send(name, codec.encodeMethodCall(new MethodCall(method, arguments)),
callback == null ? null : new IncomingResultHandler(callback));
FlutterView的发送方法
public void send(String channel, ByteBuffer message, BinaryReply callback) {
if (!isAttached()) {
Log.d(TAG, "FlutterView.send called on a detached view, channel=" + channel);
return;
mNativeView.send(channel, message, callback);
- 调用了变量mNativeView的发送方法,mNativeView是一个FlutterNativeView,继续跟进
FlutterNativeView的发送方法
public void send(String channel, ByteBuffer message, BinaryReply callback) {
if (!isAttached()) {
Log.d(TAG, "FlutterView.send called on a detached view, channel=" + channel);
return;
dartExecutor.getBinaryMessenger().send(channel, message, callback);
- 它从dartExecutor中获取到一个BinaryMessager,然后调用了它的发送方法。
//DartExecutor.java
//部分代码
@NonNull
private final BinaryMessenger binaryMessenger;
public DartExecutor(@NonNull FlutterJNI flutterJNI, @NonNull AssetManager assetManager) {
this.flutterJNI = flutterJNI;
this.assetManager = assetManager;
this.dartMessenger = new DartMessenger(flutterJNI);
dartMessenger.setMessageHandler("flutter/isolate", isolateChannelMessageHandler);
this.binaryMessenger = new DefaultBinaryMessenger(dartMessenger);
public BinaryMessenger getBinaryMessenger() {
return binaryMessenger;
- 很明显是调用了BinaryMessenger的发送方法,看一下DefaultBinaryMessenger
DefaultBinaryMessenger的发送方法
private static class DefaultBinaryMessenger implements BinaryMessenger {
private final DartMessenger messenger;
private DefaultBinaryMessenger(@NonNull DartMessenger messenger) {
this.messenger = messenger;
public void send(@NonNull String channel, @Nullable ByteBuffer message) {
messenger.send(channel, message, null);
public void send(@NonNull String channel, @Nullable ByteBuffer message, @Nullable BinaryMessenger.BinaryReply callback) {
messenger.send(channel, message, callback);
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessenger.BinaryMessageHandler handler) {
messenger.setMessageHandler(channel, handler);
- DefaultBinaryMessenger就是对DartMessenger的一个封装,啥都没有做。
DartMessenger的发送过程
@Override
@UiThread
public void send(@NonNull String channel, @NonNull ByteBuffer message) {
Log.v(TAG, "Sending message over channel '" + channel + "'");
send(channel, message, null);
@Override
public void send(
@NonNull String channel,
@Nullable ByteBuffer message,
@Nullable BinaryMessenger.BinaryReply callback
Log.v(TAG, "Sending message with callback over channel '" + channel + "'");
int replyId = 0;
if (callback != null) {
replyId = nextReplyId++;
pendingReplies.put(replyId, callback);//维护一个replyId为key,callback为value的hashmap
if (message == null) {
flutterJNI.dispatchEmptyPlatformMessage(channel, replyId);
} else {
flutterJNI.dispatchPlatformMessage(channel, message, message.position(), replyId);
- 如果有方法回调callback,就会生成一个replyId,然后把方法回调和replyId加入到一个map;
- 如果没有就直接发送消息了。
- 如果消息体为空,就发送一个空消息;
- 如果有消息内容,就把消息发送过去。还会携带一个replyId,这个会在回调的时候有用。
FlutterJni分发消息
public void dispatchPlatformMessage(@NonNull String channel, @Nullable ByteBuffer message, int position, int responseId) {
ensureRunningOnMainThread();//确保在主线程执行
if (isAttached()) {
nativeDispatchPlatformMessage(
nativePlatformViewId,
channel,
message,
position,
responseId
} else {
Log.w(TAG, "Tried to send a platform message to Flutter, but FlutterJNI was detached from native C++. Could not send. Channel: " + channel + ". Response ID: " + responseId);
// Send a data-carrying platform message to Dart.
private native void nativeDispatchPlatformMessage(
long nativePlatformViewId,
@NonNull String channel,
@Nullable ByteBuffer message,
int position,
int responseId
- 最终调到了c++层面,通过c++的dart虚拟机,把消息传递给了flutter。
2.2.3、flutter向原生传递消息
已经确定了消息是通过c++层面的虚拟机,发送到flutter,那么flutter的消息肯定也是要从c++层面的虚拟机发送过来,c++虚拟机就是原生与flutter通讯的桥梁。
android与c++的沟通肯定是通过FlutterJni这个类。
FlutterJni层做了什么
//FlutterJni讲自己绑定到了c++,
public void attachToNative(boolean isBackgroundView) {
ensureRunningOnMainThread();
ensureNotAttachedToNative();
nativePlatformViewId = nativeAttach(this, isBackgroundView);
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
- 把java类FlutterJNI传入jni
- 为了回调用java类中的方法
//处理从flutter主动call过来的消息
//Called by native on the UI thread
private void handlePlatformMessage(@NonNull final String channel, byte[] message, final int replyId) {
if (platformMessageHandler != null) {
platformMessageHandler.handleMessageFromDart(channel, message, replyId);
//用来处理方法调用到flutter以后的回调
private void handlePlatformMessageResponse(int replyId, byte[] reply) {
if (platformMessageHandler != null) {
platformMessageHandler.handlePlatformMessageResponse(replyId, reply);
- 最终调动的了platformMessageHandler的分发的方法;
PlatformMessageHandler
//通过这个方法绑定了一个方法的回调;
public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformMessageHandler) {
ensureRunningOnMainThread();
this.platformMessageHandler = platformMessageHandler;
- PlatformMessageHandler是一个接口,处理从Dart层call的消息
- DartMessenger是他的实现类,再看一下DartExecutor的一些方法;
DartExecutor
public DartExecutor(@NonNull FlutterJNI flutterJNI, @NonNull AssetManager assetManager) {
this.flutterJNI = flutterJNI;
this.assetManager = assetManager;
this.dartMessenger = new DartMessenger(flutterJNI);
dartMessenger.setMessageHandler("flutter/isolate", isolateChannelMessageHandler);
this.binaryMessenger = new DefaultBinaryMessenger(dartMessenger);
public void onAttachedToJNI() {
Log.v(TAG, "Attached to JNI. Registering the platform message handler for this Dart execution context.");
flutterJNI.setPlatformMessageHandler(dartMessenger);
- 在构造函数里面,构建DartMessager的对象,然后在调动onAttachToJNI的时候,注册给了FlutterJNI类。
- 所以方法的处理是在DartMessager这个类中
分支一、DartMessager中处理flutter的回调信息
@Override
public void handlePlatformMessageResponse(int replyId, @Nullable byte[] reply) {
Log.v(TAG, "Received message reply from Dart.");
BinaryMessenger.BinaryReply callback = pendingReplies.remove(replyId);
if (callback != null) {
try {
Log.v(TAG, "Invoking registered callback for reply from Dart.");
callback.reply(reply == null ? null : ByteBuffer.wrap(reply));
} catch (Exception ex) {
Log.e(TAG, "Uncaught exception in binary message reply handler", ex);
先看下面那个方法,这个是原生调用flutter以后的回复。里面有一个replayId,和reply字节数组。
- 首先根据replyid找到刚才发送消息时保存的callback,
- 如果找到了,就把reply转化为bytebuff调用出去。
- BinaryReply的实现类为IncomingResultHandler
MethodChannel中IncomingResultHandler分析
private final class IncomingResultHandler implements BinaryReply {
private final Result callback;
IncomingResultHandler(Result callback) {
this.callback = callback;
@Override
@UiThread
public void reply(ByteBuffer reply) {
try {
if (reply == null) {
callback.notImplemented();
} else {
try {
callback.success(codec.decodeEnvelope(reply));
} catch (FlutterException e) {
callback.error(e.code, e.getMessage(), e.details);
} catch (RuntimeException e) {
Log.e(TAG + name, "Failed to handle method call result", e);
- IncomingResultHandler包装了Result,最终消息在IncomingResultHandler#reply中解码后,传给了callback。
- 我们从原生调用一个方法,然后获得结果的整个过程就是这样子。
- 如果是从flutter主动调动的消息,则是另一个线路。在DartMessage#handleMessageFromDart这个方法中,处理了flutter主动的消息。
分支二、DartMessager中处理flutter的主动调用原生信息
@Override
//三个参数,通道名字,消息的字节,从flutter端传递过来的replyId,
public void handleMessageFromDart(
@NonNull final String channel,
@Nullable byte[] message,
final int replyId
Log.v(TAG, "Received message from Dart over channel '" + channel + "'");
//1、根据通道名字找到对象的处理类
BinaryMessenger.BinaryMessageHandler handler = messageHandlers.get(channel);
final DartMessengerTaskQueue taskQueue = (handlerInfo != null) ? handlerInfo.taskQueue : null;
Runnable myRunnable =
() -> {
Trace.beginSection("DartMessenger#handleMessageFromDart on " + channel);
try {
invokeHandler(handlerInfo, message, replyId);
if (message != null && message.isDirect()) {
// This ensures that if a user retains an instance to the ByteBuffer and it happens to
// be direct they will get a deterministic error.
message.limit(0);
} finally {
// This is deleting the data underneath the message object.
flutterJNI.cleanupMessageData(messageData);
Trace.endSection();
private void invokeHandler(
@Nullable HandlerInfo handlerInfo, @Nullable ByteBuffer message, final int replyId) {
// Called from any thread.
if (handlerInfo != null) {
try {
//转发给注册的handler去处理消息
handlerInfo.handler.onMessage(message, new Reply(flutterJNI, replyId));
} catch (Exception ex) {
Log.e(TAG, "Uncaught exception in binary message listener", ex);
flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
} catch (Error err) {
handleError(err);
} else {
Log.v(TAG, "No registered handler for message. Responding to Dart with empty reply message.");
flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
- 最终回调到MethodChannel中IncomingMethodCallHandler中
2.2.4、handler是什么时候注册的?
//MethodChannel
public void setMethodCallHandler(final @Nullable MethodCallHandler handler) {
//这个messager是flutterView
messenger.setMessageHandler(name,
handler == null ? null : new IncomingMethodCallHandler(handler));
//FlutterView.java
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
//mNativeView 是FlutterNativeView
mNativeView.setMessageHandler(channel, handler);
//FlutterNativeView.java
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
dartExecutor.getBinaryMessenger().setMessageHandler(channel, handler);
// DartMessage.java
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessenger.BinaryMessageHandler handler) {
if (handler == null) {
Log.v(TAG, "Removing handler for channel '" + channel + "'");
messageHandlers.remove(channel);
} else {
Log.v(TAG, "Setting handler for channel '" + channel + "'");
messageHandlers.put(channel, handler);
- 最终又到了DartExecutor中,从上面的分析可以知道, dartExecutor.getBinaryMessenger()获得的是一个 DefaultBinaryMessenger;
- 而DefaultBinaryMessenger中持有了DartMessager。
- 所以setMessageHandler最终被设置到DartMessage中。
- 所以从c++层面来了消息以后,就会回调到MethodChannel中;
- 在MethodChannel中设置的是一个MethodCallHandler,最后被包装为实现了BinaryMessageHandler的IncomingMethodCallHandler
private final class IncomingMethodCallHandler implements BinaryMessageHandler {
private final MethodCallHandler handler;
IncomingMethodCallHandler(MethodCallHandler handler) {
this.handler = handler;
"DartMessage 调用这个方法把消息传递过来"
@Override
@UiThread
public void onMessage(ByteBuffer message, final BinaryReply reply) {
//1、解码信息MethodCall中包含了方法名字和参数
final MethodCall call = codec.decodeMethodCall(message);
try {
//2、调用回调处理,如果需要回传结果,就调用Result的success方法。"
handler.onMethodCall(call, new Result() {
@Override
public void success(Object result) {
reply.reply(codec.encodeSuccessEnvelope(result));
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
reply.reply(codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails));
@Override
public void notImplemented() {
reply.reply(null);
} catch (RuntimeException e) {
Log.e(TAG + name, "Failed to handle method call", e);
reply.reply(codec.encodeErrorEnvelope("error", e.getMessage(), null));
2.3、从Dart角度分析
用一张图说明,不做源码分析了
三、时序图
从Flutter调用原生开始
原生返回Flutter数据
参考大佬两幅图
原文链接:https://juejin.cn/post/7068224984237211678
在跟甲方合作中,需要开发一个App,除了店长管理日常日报和订单退款之外,还需要实现通过消息推送将每笔订单进行语音播报。App开发开始从其他团队借调一个做Android的人过来先完成了Android开发,ios本打算靠后一点发布。刚好遇到组织架构重组,ios就停滞了。离甲方要求的时间只有一个月时间了,产品和运营就来找我们技术团队说App能不能做,但是重新学习一门新的语言,确实一个非常大的挑战。恰好当时我很感兴趣flutter开发app,就主动提出来接这个锅。
上篇文章 Flutter 路由管理 Route、Navigator 使用示例 我们了解了页面跳转的功能。但仅限于 Flutter 页面。那么Flutter 页面和原生页面之间如何跳转呢?
在 Flutter 开发中,我们经常需要进行网络请求,而 Dio 是一个强大的网络请求库,支持多种请求方式,具有高效、简洁的特点。但是每次发起请求时都需要编写一些公共代码,如设置请求头、处理错误等,这些代码会让我们的业务逻辑变得繁琐,为了提高开发效率,我们可以将这些公共代码进行封装,方便我们在业务中直接调用。
上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信。
并且也看到了 Flutter 内部 EventChannel 源码也是对 MethodChannel 的封装。
因此这篇我们来说下如何通过 MethodChannel 实现 Android -> Flutter 的通信。
至于 Flutter -> Android 的...
二 MethodChannel通信示例
2.1 创建Flutter端MethodChannel
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main()
Dart和原生通信
一次典型的方法调用过程类似网络调用,由作为客户端的 Flutter,通过方法通道向作为服务端的原生代码宿主发送方法调用请求,原生代码宿主在监听到方法调用的消息后,调用平台相关的 API 来处理 Flutter 发起的请求,最后将处理完毕的结果通过方法通道回发至 Flutter。调用过程如下图所示:
1. 基本用法
以跳转应用市场为例
//声明MethodChannel
const platform = MethodChannel('channelName');
//处理按钮点击
上次从一个路径插件看来一下Flutter中如何调用iOS和Android中的方法以及平台如何返回值给Flutter框架。今天就来详细讲讲MethodChannel是如何连同另一个世界的。
1.从吐司弹框开始说起(Android端/Java)
想要达成的效果是这样使用可以弹出一个时间较长的吐司
这个示例要讲述的是Flutter中如何向平台传递参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aNH1nR59-1629539325555)(https://user-g.
本篇从官方案例获取系统版本号的分析,到模仿官方案例加入自己调用不同原生返回内容,以及通过简单传递参数给原生加工后返回给flutter的案例来整体对MethodChannel在插件编写中的使用进行了全面的描述...
1.1 flutter端发送消息方式是:
class InteractUtil {
static const platform = const MethodChannel("com.yourname.yourname/method");
factory InteractUtil() => _getInstance();
static InteractUtil get instance .
NativeCallUtils.getNativeReslut(params : map).then((value) {
setState(() {
result = "${map['a']} +${map['b']} = ${value}";
import 'package:flutter/s
list set map
链表list 允许重复元素 元素位置与插入位置
set集 只能增删 不允许出现重复元素,可以用来去重,重写hashcode和equals方法 shift alt进行选择 不保证位置 没有下标 只允许有一个空 hash tree可以有顺序,利用接口比字符串
Map底层是set
map 是映射结构:有key-valu
Dart4Flutter – 03 – 类和泛型
Dart4Flutter – 04 – 异步和库
Dart4Flutter - 拾遗01 - flutter-dart环境搭建
Dart4Flutter - 不可变性
Flutter入门 - 状态管理
Flutter 入门实例1
Flut...
Flutter开发中或多或少都需要和原生端做一些交互,Flutter SDK中也为开发者提供了MethodChannel/EventChannel实现了Flutter调用原生端以及原生端调用Flutter。
MethodChannel
Flutter与原生端方法调用使用的是MethodChannel,它是双向通信Flutter和原生端都可以主动发起
Flutter端调用原生方法
Flutter端调用
const MethodChannel _channel =
MethodChannel(
Flutter应用中修复AndroidX崩溃:
https://blog.csdn.net/ytfunnysite/article/details/88313305
webview_flutter:0.2.0
webview_flutter报错:
E/MethodChannel#flutter/platform_views(27071): Failed to handle method ca...