MethodChannel实现原理
从android端分析MethodChannel的实现原理,入口选在使用MethodChannel的使用的地方是最合适的。
首先看一下如果使用
//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) {
//呼叫成功
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
//呼叫出现异常
}
@Override
public void notImplemented() {
//flutter没有对应的实现方法
}
});
Android原生端和flutter端实现通讯完全靠上面的方法。
看一下MethodChannel的构造函数
public MethodChannel(BinaryMessenger messenger, String name) {
this(messenger, name, StandardMethodCodec.INSTANCE);
}
入参是一个通讯BinaryMessenger , 这是一个接口,我们使用的时候通常是传入一个FlutterView,因为FlutterView实现了这个接口。
先看一下消息发送的过程:
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));
}
最终是使用构造函数传入的BinaryMessenger实现类来发送消息,发送的信息有三个,
- 通道的名字
- 方法名字加上参数经过编码转化为一个bytebuff
- 方法回调 IncomingResultHandler()后面会讲这个方法回调;
然后看一下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,继续跟进
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;
}
很明显是调用了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的一个封装,啥都没有做。不知道这个类存在有什么意义,那就接着看DartMessager的发送方法
@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);
}
if (message == null) {
flutterJNI.dispatchEmptyPlatformMessage(channel, replyId);
} else {
flutterJNI.dispatchPlatformMessage(channel, message, message.position(), replyId);
}
}
如果有方法回调callback,就会生成一个replyId,然后把方法回调和replyId加入到一个map,如果没有就直接发送消息了。
如果消息体为空,就发送一个空消息,如果有消息内容,就把消息发送过去。还会携带一个replyId,这个会在回调的时候有用。
最终走到了flutterJni的分发方法。
//FlutterJni.java
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。
消息如何从flutter传递过来?
到现在我们已经确定了我的消息是通过c++层面的虚拟机,发送到flutter,那么flutter的消息肯定也是要从c++层面的虚拟机发送过来,c++虚拟机就是原生与flutter通讯的桥梁。
android与c++的沟通肯定是通过FlutterJni这个类。
//FlutterJni讲自己绑定到了c++,
public void attachToNative(boolean isBackgroundView) {
ensureRunningOnMainThread();
ensureNotAttachedToNative();
nativePlatformViewId = nativeAttach(this, isBackgroundView);
}
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
如果了解jni的知识,我们就能知道,把java类传入jni就是为了调用java类中的 方法。找了一下,
//用来处理从flutter主动call过来的消息
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的分发的方法;
//通过这个方法绑定了一个方法的回调;
public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformMessageHandler) {
ensureRunningOnMainThread();
this.platformMessageHandler = platformMessageHandler;
}
PlatformMessageHandler是一个接口,找到他的实现类就找到了处理的地方;
DartMessenger是他的实现类,再看一下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这个类中
@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
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主动的消息。
@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);
if (handler != null) {
try {
Log.v(TAG, "Deferring to registered handler to process message.");
"2、解码数据并调用onMessage传递消息 ,注意一下这个Reply,下面会讲到"
final ByteBuffer buffer = (message == null ? null : ByteBuffer.wrap(message));
handler.onMessage(buffer, new Reply(flutterJNI, replyId));
} catch (Exception ex) {
Log.e(TAG, "Uncaught exception in binary message listener", ex);
"异常处理"
flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
}
} else {
Log.v(TAG, "No registered handler for message. Responding to Dart with empty reply message.");
"未实现通道处理"
flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
}
}
处理类如何添加到messageHandlers中?
// 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);
}
}
我们正向的在看一下代码。从MethodChannel中的注册来看。
//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);
}
最终又到了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) {
"解码信息 MethodCall中包含了方法名字 和 参数"
final MethodCall call = codec.decodeMethodCall(message);
try {
"调用回调处理,如果需要回传结果,就调用Result的success方法。"
handler.onMethodCall(call, new Result() {
@Override
public void success(Object result) {
"这里面调用BinaryReply的reply方法传递给c++"
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));
}
}
}
BinaryReply的一个实现类为Reply,最终通过这个把结果回传回去。看源码!!!!
private static class Reply implements BinaryMessenger.BinaryReply {
@NonNull
private final FlutterJNI flutterJNI;
private final int replyId;
private final AtomicBoolean done = new AtomicBoolean(false);
Reply(@NonNull FlutterJNI flutterJNI, int replyId) {
this.flutterJNI = flutterJNI;
this.replyId = replyId;
}
@Override
public void reply(@Nullable ByteBuffer reply) {
if (done.getAndSet(true)) {
throw new IllegalStateException("Reply already submitted");
}
if (reply == null) {
//如果结果没有信息,直接调用,并回传replyId
flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
} else {
//如果有信息,调用jni的这个方法,,把信息和replyid一起传回去。
flutterJNI.invokePlatformMessageResponseCallback(replyId, reply, reply.position());
}
}
}
到此为止。android端的消息机制已经分析完毕,关键的两个核心类,FlutterJni.java DartMessager.java
网友评论