流程圖如下:
1晚唇、發(fā)送和接收
1.1 flutter端發(fā)送消息方式是:
class InteractUtil {
static const platform = const MethodChannel("com.yourname.yourname/method");
factory InteractUtil() => _getInstance();
static InteractUtil get instance => _getInstance();
static InteractUtil _instance;
InteractUtil._internal();
static InteractUtil _getInstance() {
if (_instance == null) {
_instance = new InteractUtil._internal();
}
return _instance;
}
Future<String> customMethodName(
String parameter1, String parameter2) async {
Future<String> result;
try {
print("customMethodName $parameter1 and $parameter2");
result = await platform.invokeMethod("customMethodName", {
"parameter1": parameter1,
"parameter2": parameter2,
});
} on PlatformException catch (e) {
print(e.toString());
}
return result;
}
}
1.2 Android端接收消息的方式是:
class MainActivity : FlutterActivity() {
val METHOD_CHANNEL = "com.yourname.yourname/method"
override fun onCreate(savedInstanceState: Bundle?) {
FlutterMain.startInitialization(this)
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
MethodChannel(flutterView, METHOD_CHANNEL).setMethodCallHandler { p0, p1 ->
Log.d(TAG, "method is ${p0.method}")
when (p0.method) {
"customMethodName" -> {
val parameter1 = p0.argument<String>("parameter1") as String
val parameter2 = p0.argument<String>("parameter2") as String
}
}
}
}
}
p0是MethodCall類型,p1是Result類型
兩端的MethodChannel name必須一致癣缅,另外flutter端調(diào)用invokeMethod 的方法名稱要在Android或iOS端有定義。
2、flutter端
2.1 MethodChannel初始化
MethodChannel構(gòu)造函數(shù)如下:
const MethodChannel(this.name, [this.codec = const StandardMethodCodec(), BinaryMessenger binaryMessenger ])
: assert(name != null),assert(codec != null),
_binaryMessenger = binaryMessenger;
先初始化了一個StandardMethodCodec對象李滴,看看構(gòu)造函數(shù)突硝,如下:
const StandardMethodCodec([this.messageCodec = const StandardMessageCodec()]);
StandardMethodCodec實現(xiàn)了MethodCodec接口
構(gòu)造函數(shù)中又初始化了一個StandardMessageCodec對象测摔,StandardMessageCodec實現(xiàn)了MessageCodec接口。
2.2 _binaryMessenger初始化
MethodChannel初始化成員變量的時候解恰,會初始化_binaryMessenger參數(shù)锋八,也就是set,看看定義:
BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger; // ignore: deprecated_member_use_from_same_package
final BinaryMessenger _binaryMessenger;
此處的binaryMessenger是null护盈,但是下次當(dāng)需要get的時候會走defaultBinaryMessenger參數(shù)挟纱,這個參數(shù)來自哪里呢?在src\services\binary_messenger.dart
文件中定義了get方法:
BinaryMessenger get defaultBinaryMessenger {
return ServicesBinding.instance.defaultBinaryMessenger;
}
看看ServicesBinding的defaultBinaryMessenger怎么初始化的:
packages\flutter\lib\src\services\binding.dart\ServicesBinding
mixin ServicesBinding on BindingBase {
@override
void initInstances() {
_instance = this;
_defaultBinaryMessenger = createBinaryMessenger();
window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
SystemChannels.system.setMessageHandler(handleSystemMessage);
}
BinaryMessenger get defaultBinaryMessenger => _defaultBinaryMessenger;
BinaryMessenger _defaultBinaryMessenger;
}
同一個文件中看看createBinaryMessenger方法:
BinaryMessenger createBinaryMessenger() {
return const _DefaultBinaryMessenger._();
}
創(chuàng)建了_DefaultBinaryMessenger對象腐宋,其繼承自BinaryMessenger紊服。
2.3 window.onPlatformMessage
將defaultBinaryMessenger.handlePlatformMessage方法設(shè)置給window.onPlatformMessage。也就是_DefaultBinaryMessenger的handlePlatformMessage方法胸竞。
看看onPlatformMessage的定義:
lib\ui\window.dart\Window
PlatformMessageCallback get onPlatformMessage => _onPlatformMessage;
PlatformMessageCallback _onPlatformMessage;
Zone _onPlatformMessageZone;
set onPlatformMessage(PlatformMessageCallback callback) {
_onPlatformMessage = callback;
_onPlatformMessageZone = Zone.current;
}
這里的callback就是_DefaultBinaryMessenger的handlePlatformMessage方法欺嗤。
看看這個方法的定義:
packages\flutter\lib\src\services\binding.dart\_DefaultBinaryMessenger
@override
Future<void> handlePlatformMessage(String channel,ByteData data,ui.PlatformMessageResponseCallback callback,) async {
ByteData response;
try {
final MessageHandler handler = _handlers[channel];
if (handler != null) {
response = await handler(data);
} else {
ui.channelBuffers.push(channel, data, callback);
callback = null;
}
} catch (exception, stack) {
} finally {
if (callback != null) {
callback(response);
}
}
}
onPlatformMessage接收到特定平臺的消息時,就會調(diào)用到handlePlatformMessage方法卫枝。window.onPlatformMessage是一個全局的變量煎饼,在很多消息傳遞的地方都可以調(diào)用。
2.4 setMessageHandler
handleSystemMessage在ServicesBinding中校赤,可以被其他Binding重載腺占,如下:
Future<void> handleSystemMessage(Object systemMessage) async { }
看看system變量:
packages\flutter\lib\src\services\system_channels.dart\SystemChannels
static const BasicMessageChannel<dynamic> system = BasicMessageChannel<dynamic>(
'flutter/system',
JSONMessageCodec(),
);
通過JSON來編解碼消息。JSONMessageCodec實現(xiàn)了MessageCodec接口痒谴。
2.5 MethodChannel.invokeMethod
我們自己的dart調(diào)用invokeMethod方法發(fā)送消息衰伯,如下:
Future<T> invokeMethod<T>(String method, [ dynamic arguments ]) async {
assert(method != null);
final ByteData result = await binaryMessenger.send(name,codec.encodeMethodCall(MethodCall(method, arguments)),);
if (result == null) {
throw MissingPluginException('No implementation found for method $method on channel $name');
}
final T typedResult = codec.decodeEnvelope(result);
return typedResult;
}
其實還有invokeListMethod和invokeMapMethod方法,最終都是執(zhí)行到invokeMethod方法积蔚。
binaryMessenger對應(yīng)的類是_DefaultBinaryMessenger意鲸,codec對應(yīng)的是StandardMethodCodec類。
2.5.1 數(shù)據(jù)編碼
此處先將方法和參數(shù)通過MethodCall封裝,然后在StandardMethodCodec中編碼怎顾,看看具體怎么編碼的:
StandardMethodCodec
@override
ByteData encodeMethodCall(MethodCall call) {
final WriteBuffer buffer = WriteBuffer();
messageCodec.writeValue(buffer, call.method);
messageCodec.writeValue(buffer, call.arguments);
return buffer.done();
}
看看WriteBuffer的構(gòu)造函數(shù):
packages\flutter\lib\src\foundation\serialization.dart\WriteBuffer
WriteBuffer() {
_buffer = Uint8Buffer();
_eightBytes = ByteData(8);
_eightBytesAsList = _eightBytes.buffer.asUint8List();
}
WriteBuffer構(gòu)造函數(shù)中初始化的Uint8Buffer類型读慎,可以看做是一個List<int>,而ByteData可以看做是一個byte數(shù)組槐雾,長度為8夭委。
messageCodec是一個StandardMessageCodec類型,看看他的writeValue方法:
void writeValue(WriteBuffer buffer, dynamic value) {
writeSize(buffer, value.length);
buffer.putxxx(_valueFloat64);
}
根據(jù)value的不同類型募强,put到不同的集合中株灸。如果value是int類型,就放到_buffer中擎值;如果是float類型慌烧,占8位,放到_eightBytes中鸠儿;而我們的method是String類型屹蚊,將其轉(zhuǎn)換為utf-8之后,轉(zhuǎn)成byte數(shù)組放到_buffer中进每。對于value占位大于1的汹粤,先寫占用長度,再寫占用值田晚。不同的長度對應(yīng)不同的數(shù)字嘱兼,如下:
static const int _valueNull = 0;
static const int _valueTrue = 1;
static const int _valueFalse = 2;
static const int _valueInt32 = 3;
static const int _valueInt64 = 4;
static const int _valueLargeInt = 5;
static const int _valueFloat64 = 6;
static const int _valueString = 7;
static const int _valueUint8List = 8;
static const int _valueInt32List = 9;
static const int _valueInt64List = 10;
static const int _valueFloat64List = 11;
static const int _valueList = 12;
static const int _valueMap = 13;
看done方法:
packages\flutter\lib\src\foundation\serialization.dart\WriteBuffer
ByteData done() {
final ByteData result = _buffer.buffer.asByteData(0, _buffer.lengthInBytes);
_buffer = null;
return result;
}
其實是將剛才write進(jìn)去的數(shù)據(jù)轉(zhuǎn)成一個byte數(shù)組返回,這個數(shù)組的代表就是ByteData對象肉瓦。
2.6 發(fā)送消息(binaryMessenger.send)
上面提到binaryMessenger是_DefaultBinaryMessenger類型遭京,看看里面的send方法:
@override
Future<ByteData> send(String channel, ByteData message) {
final MessageHandler handler = _mockHandlers[channel];
if (handler != null)
return handler(message);
return _sendPlatformMessage(channel, message);
}
這里的_mockHandlers是Map<String, MessageHandler>類型胃惜,而MessageHandler的類型卻是:
typedef MessageHandler = Future<ByteData> Function(ByteData message);
一個函數(shù)泞莉。所以send方法最開始從這個Map中查找channel名稱對應(yīng)的函數(shù)是否存在,存在的話船殉,直接調(diào)用鲫趁,而不用執(zhí)行后面的方法了。明顯的利虫,這里需要調(diào)用_sendPlatformMessage方法:
Future<ByteData> _sendPlatformMessage(String channel, ByteData message) {
final Completer<ByteData> completer = Completer<ByteData>();
ui.window.sendPlatformMessage(channel, message, (ByteData reply) {
completer.complete(reply);
});
return completer.future;
}
看看ui.window的sendPlatformMessage方法:
ui\window.dart\Window
void sendPlatformMessage(String name,ByteData data,PlatformMessageResponseCallback callback) {
final String error = _sendPlatformMessage(name, _zonedPlatformMessageResponseCallback(callback), data);
}
String _sendPlatformMessage(String name,
PlatformMessageResponseCallback callback,
ByteData data) native 'Window_sendPlatformMessage';
最終調(diào)用到了native的Window_sendPlatformMessage方法:
ui\window\window.cc\Window
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
}
void _SendPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&SendPlatformMessage, args);
}
Dart_Handle SendPlatformMessage(Dart_Handle window,const std::string& name,Dart_Handle callback,Dart_Handle data_handle) {
UIDartState* dart_state = UIDartState::Current();
if (!dart_state->window()) {
return tonic::ToDart(
"Platform messages can only be sent from the main isolate");
}
fml::RefPtr<PlatformMessageResponse> response;
if (!Dart_IsNull(callback)) {
response = fml::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(dart_state, callback),
dart_state->GetTaskRunners().GetUITaskRunner());
}
if (Dart_IsNull(data_handle)) {
dart_state->window()->client()->HandlePlatformMessage(
fml::MakeRefCounted<PlatformMessage>(name, response));
} else {
tonic::DartByteData data(data_handle);
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
dart_state->window()->client()->HandlePlatformMessage(fml::MakeRefCounted<PlatformMessage>(name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),response));
}
return Dart_Null();
}
DartCallStatic方法將args轉(zhuǎn)換成了dart可處理的變量類型挨厚。
2.6.1 預(yù)定義返回
這里response對應(yīng)的是PlatformMessageResponseDart類型,看看這個方法:
ui\window\platform_message_response_dart.cc\PlatformMessageResponseDart
mMessageResponseDart::PlatformMessageResponseDart(
tonic::DartPersistentValue callback,
fml::RefPtr<fml::TaskRunner> ui_task_runner)
: callback_(std::move(callback)),
ui_task_runner_(std::move(ui_task_runner)) {}
void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
if (callback_.is_empty())
return;
FML_DCHECK(!is_complete_);
is_complete_ = true;
ui_task_runner_->PostTask(fml::MakeCopyable(
[callback = std::move(callback_), data = std::move(data)]() mutable {
std::shared_ptr<tonic::DartState> dart_state = callback.dart_state().lock();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle byte_buffer = WrapByteData(std::move(data));
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}
調(diào)用完成時會回調(diào)到這里,最終會調(diào)用callback對應(yīng)的閉包糠惫。
2.6.3 處理消息(HandlePlatformMessage)
接下來執(zhí)行HandlePlatformMessage疫剃,看看一系列調(diào)用堆棧:
runtime\runtime_controller.cc
// |WindowClient|
void RuntimeController::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
client_.HandlePlatformMessage(std::move(message));
}
shell\common\engine.cc
void Engine::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
if (message->channel() == kAssetChannel) {
HandleAssetPlatformMessage(std::move(message));
} else {
delegate_.OnEngineHandlePlatformMessage(std::move(message));
}
}
shell\common\shell.cc
// |Engine::Delegate|
void Shell::OnEngineHandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
if (message->channel() == kSkiaChannel) {
HandleEngineSkiaMessage(std::move(message));
return;
}
task_runners_.GetPlatformTaskRunner()->PostTask([view = platform_view_->GetWeakPtr(), message = std::move(message)]() {
if (view) {
view->HandlePlatformMessage(std::move(message));
}
});
}
view對應(yīng)類,以Android平臺為例:
shell\platform\android\platform_view_android.cc
// |PlatformView|
void PlatformViewAndroid::HandlePlatformMessage(fml::RefPtr<flutter::PlatformMessage> message) {
JNIEnv* env = fml::jni::AttachCurrentThread();
fml::jni::ScopedJavaLocalRef<jobject> view = java_object_.get(env);
if (view.is_null())
return;
int response_id = 0;
if (auto response = message->response()) {
response_id = next_response_id_++;
pending_responses_[response_id] = response;
}
auto java_channel = fml::jni::StringToJavaString(env, message->channel());
if (message->hasData()) {
fml::jni::ScopedJavaLocalRef<jbyteArray> message_array(env, env->NewByteArray(message->data().size()));
env->SetByteArrayRegion(message_array.obj(), 0, message->data().size(), reinterpret_cast<const jbyte*>(message->data().data()));
message = nullptr;
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
FlutterViewHandlePlatformMessage(env, view.obj(), java_channel.obj(),message_array.obj(), response_id);
} else {
message = nullptr;
// This call can re-enter in InvokePlatformMessageXxxResponseCallback.
FlutterViewHandlePlatformMessage(env, view.obj(), java_channel.obj(),nullptr, response_id);
}
}
接下來調(diào)用FlutterViewHandlePlatformMessage方法硼讽,這個方法對應(yīng)的是Java jni注冊的方法巢价,看看方法體:
shell\platform\android\platform_view_android_jni.cc
void FlutterViewHandlePlatformMessage(JNIEnv* env, jobject obj,jstring channel,jobject message,jint responseId) {
env->CallVoidMethod(obj, g_handle_platform_message_method, channel, message,responseId);
FML_CHECK(CheckException(env));
}
看看g_handle_platform_message_method注冊的地方:
shell\platform\android\platform_view_android_jni.cc
g_handle_platform_message_method = env->GetMethodID(g_flutter_jni_class->obj(), "handlePlatformMessage","(Ljava/lang/String;[BI)V");
2.6.4 到系統(tǒng)平臺處理消息
對應(yīng)Java中的handlePlatformMessage方法,參數(shù)是String,byte數(shù)組壤躲,int城菊。看看handlePlatformMessage方法:
shell\platform\android\io\flutter\embedding\engine\FlutterJNI.java
private void handlePlatformMessage(
@NonNull final String channel, byte[] message, final int replyId) {
if (platformMessageHandler != null) {
platformMessageHandler.handleMessageFromDart(channel, message, replyId);
}
}
在FlutterJNI類中碉克,通過setPlatformMessageHandler方法設(shè)置platformMessageHandler對象凌唬,看看是哪里設(shè)置的。還記得FlutterNativeView構(gòu)造函數(shù)中漏麦,最后調(diào)用了attach方法客税,如下:
shell\platform\android\io\flutter\view\FlutterNativeView.java
private void attach(FlutterNativeView view, boolean isBackgroundView) {
mFlutterJNI.attachToNative(isBackgroundView);
dartExecutor.onAttachedToJNI();
}
看看onAttachedToJNI方法:
shell\platform\android\io\flutter\embedding\engine\dart\DartExecutor.java
public void onAttachedToJNI() {
flutterJNI.setPlatformMessageHandler(dartMessenger);
}
這里的dartMessenger對應(yīng)的是DartMessenger類,所以此處的platformMessageHandler對應(yīng)的是DartMessenger對象唁奢。另外在dartMessenger初始化的時候霎挟,會調(diào)用setMessageHandler方法:
shell\platform\android\io\flutter\embedding\engine\dart\DartExecutor.java
private final BinaryMessenger.BinaryMessageHandler isolateChannelMessageHandler =
new BinaryMessenger.BinaryMessageHandler() {
@Override
public void onMessage(ByteBuffer message, final BinaryReply callback) {
isolateServiceId = StringCodec.INSTANCE.decodeMessage(message);
if (isolateServiceIdListener != null) {
isolateServiceIdListener.onIsolateServiceIdAvailable(isolateServiceId);
}
}
};
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);
}
這里的isolateChannelMessageHandler對應(yīng)的是BinaryMessenger.BinaryMessageHandler類,channel name是flutter/isolate麻掸。在DartMessenger中酥夭,通過setMessageHandler方法將channel name和MessageHandler放到了messageHandlers這個Map對象中。如下:
@Override
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);
}
}
回到開始調(diào)用handleMessageFromDart的地方脊奋,這個方法在DartMessenger中有定義:
shell\platform\android\io\flutter\embedding\engine\dart\DartMessenger.java
@Override
public void handleMessageFromDart(
@NonNull final String channel, @Nullable byte[] message, final int replyId) {
Log.v(TAG, "Received message from Dart over channel '" + channel + "'");
BinaryMessenger.BinaryMessageHandler handler = messageHandlers.get(channel);
if (handler != null) {
try {
Log.v(TAG, "Deferring to registered handler to process message.");
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這個Map中取出channel name對應(yīng)的MessageHandler熬北,然后回調(diào)到他的onMessage方法中。
3诚隙、Android端
3.1 MethodChannel
Android端最開始注冊接收的代碼如下:
MethodChannel(flutterView, METHOD_CHANNEL).setMethodCallHandler {
}
flutterView其實是FlutterActivityDelegate中的FlutterView flutterView對象讶隐,而FlutterView實現(xiàn)了BinaryMessenger接口。
看看MethodChannel構(gòu)造函數(shù):
MethodChannel
public MethodChannel(BinaryMessenger messenger, String name) {
this(messenger, name, StandardMethodCodec.INSTANCE);
}
public MethodChannel(BinaryMessenger messenger, String name, MethodCodec codec) {
this.messenger = messenger;
this.name = name;
this.codec = codec;
}
這里的messenger就是FlutterView類型久又。
3.2 MethodCallHandler
接下來看看MethodChannel的setMethodCallHandler方法:
shell\platform\android\io\flutter\plugin\common\MethodChannel.java
public void setMethodCallHandler(final @Nullable MethodCallHandler handler) {
messenger.setMessageHandler(name,handler == null ? null : new IncomingMethodCallHandler(handler));
}
到這里巫延,我們的handler其實是在我們的MainActivity中定義了的,只不過lamada表達(dá)式將類名隱藏地消,只顯示了閉包接收的參數(shù)炉峰。完整的形式是:
MethodChannel(flutterView, METHOD_CHANNEL).setMethodCallHandler(MethodChannel.MethodCallHandler { p0, p1 ->
}
3.2.1 IncomingMethodCallHandler
最終通過IncomingMethodCallHandler將我們的MethodCallHandler初始化給IncomingMethodCallHandler類的handler對象,如下:
private final class IncomingMethodCallHandler implements BinaryMessageHandler {
private final MethodCallHandler handler;
IncomingMethodCallHandler(MethodCallHandler handler) {
this.handler = handler;
}
public void onMessage(ByteBuffer message, final BinaryReply reply) {
}
}
這里的codec在MethodChannel構(gòu)造的時候默認(rèn)為StandardMethodCodec實例脉执。
看看messenger所屬的FlutterView中的setMessageHandler函數(shù):
FlutterView
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
mNativeView.setMessageHandler(channel, handler);
}
這里的handler就是IncomingMethodCallHandler,看看setMessageHandler的setMessageHandler方法:
FlutterNativeView
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
dartExecutor.getBinaryMessenger().setMessageHandler(channel, handler);
}
3.3 DefaultBinaryMessenger
又回到dartExecutor這里了疼阔,getBinaryMessenger()方法對應(yīng)的是DefaultBinaryMessenger,看看他的setMessageHandler方法:
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessenger.BinaryMessageHandler handler) {
messenger.setMessageHandler(channel, handler);
}
DefaultBinaryMessenger構(gòu)造的時候半夷,有初始化一個messenger對象婆廊,他對應(yīng)的是DartMessenger,就可以發(fā)現(xiàn)最終是向他所屬的Map中添加channel對應(yīng)的BinaryMessenger.BinaryMessageHandler巫橄。
messageHandlers.put(channel, handler);
這里終于將dart發(fā)送過來的消息和java層的注冊對接起來了淘邻。
3.4 MethodCallHandler中處理消息
handleMessageFromDart中通過handler執(zhí)行的onMessage方法,即IncomingMethodCallHandler類中的onMessage方法湘换,通過StandardMethodCodec解碼之后得到MethodCall對象宾舅,然后回調(diào)給MainActivity里面MethodCallHandler的onMethodCall方法敬尺。
IncomingMethodCallHandler直接處理dart來的數(shù)據(jù),并分發(fā)
public void onMessage(ByteBuffer message, final BinaryReply reply) {
final MethodCall call = codec.decodeMethodCall(message);
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));
}
});
}
MainActicity注冊Handler之后接收數(shù)據(jù)贴浙,處理數(shù)據(jù)砂吞,完成之后返回
MethodChannel(flutterView, METHOD_CHANNEL).setMethodCallHandler(MethodChannel.MethodCallHandler { p0, p1 ->
MyLog.d(TAG, "method is ${p0.method}")
when (p0.method) {
"method_name" -> {
p1.success(data)
}
}
}
4、返回
Android端處理完dart的消息之后崎溃,可以通過Result對象將需要返回的數(shù)據(jù)返回蜻直,包括成功,失敗袁串,未完成概而。
reply其實是在handleMessageFromDart方法中初始化的,handler.onMessage(buffer, new Reply(flutterJNI, replyId))
囱修。
4.1 返回成功或失敗
成功的話赎瑰,會通過StandardMethodCodec的encodeSuccessEnvelope將數(shù)據(jù)編碼:
reply.reply(codec.encodeSuccessEnvelope(result));
public ByteBuffer encodeSuccessEnvelope(Object result) {
final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
stream.write(0);
messageCodec.writeValue(stream, result);
final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
buffer.put(stream.buffer(), 0, stream.size());
return buffer;
}
先寫進(jìn)去一個成功的標(biāo)志位,messageCodec是StandardMethodCodec類型破镰,將要返回的數(shù)據(jù)寫進(jìn)一個byte數(shù)組中餐曼,然后放到ByteBuffer中,返回鲜漩。
失敗的話源譬,會有失敗原因:
reply.reply(codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails));
@Override
public ByteBuffer encodeErrorEnvelope(
String errorCode, String errorMessage, Object errorDetails) {
final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
stream.write(1);
messageCodec.writeValue(stream, errorCode);
messageCodec.writeValue(stream, errorMessage);
messageCodec.writeValue(stream, errorDetails);
final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
buffer.put(stream.buffer(), 0, stream.size());
return buffer;
}
編碼失敗數(shù)據(jù)時,與成功唯一的差別是標(biāo)志位不一樣孕似。
4.2 Reply返回數(shù)據(jù)
看看Reply的具體返回方式:
4.2.1 Reply
@Override
public void reply(@Nullable ByteBuffer reply) {
if (done.getAndSet(true)) {
throw new IllegalStateException("Reply already submitted");
}
if (reply == null) {
flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
} else {
flutterJNI.invokePlatformMessageResponseCallback(replyId, reply, reply.position());
}
}
我們這里的reply不為空踩娘,執(zhí)行invokePlatformMessageResponseCallback方法:
shell\platform\android\io\flutter\embedding\engine\FlutterJNI.java
public void invokePlatformMessageResponseCallback(int responseId, @Nullable ByteBuffer message, int position) {
if (isAttached()) {
nativeInvokePlatformMessageResponseCallback(nativePlatformViewId, responseId, message, position);
}
}
private native void nativeInvokePlatformMessageResponseCallback(long nativePlatformViewId, int responseId, @Nullable ByteBuffer message, int position);
這里的nativePlatformViewId其實是我們在應(yīng)用啟動時,初始化引擎返回給我們的一個long類型的id喉祭。
4.3 引擎中處理數(shù)據(jù)
nativeInvokePlatformMessageResponseCallback對應(yīng)注冊的native方法是InvokePlatformMessageResponseCallback:
shell\platform\android\platform_view_android_jni.cc
bool RegisterApi(JNIEnv* env) {
static const JNINativeMethod flutter_jni_methods[] = {
{
.name = "nativeInvokePlatformMessageResponseCallback",
.signature = "(JILjava/nio/ByteBuffer;I)V",
.fnPtr = reinterpret_cast<void*>(&InvokePlatformMessageResponseCallback),
},
}
}
具體看看InvokePlatformMessageResponseCallback的調(diào)用棧:
shell\platform\android\platform_view_android_jni.cc
static void InvokePlatformMessageResponseCallback(JNIEnv* env,jobject jcaller,jlong shell_holder,jint responseId,jobject message,jint position) {
ANDROID_SHELL_HOLDER->GetPlatformView()->InvokePlatformMessageResponseCallback(env,responseId,message,position);
}
shell\platform\android\platform_view_android.cc
void PlatformViewAndroid::InvokePlatformMessageResponseCallback(JNIEnv* env,jint response_id,jobject java_response_data,jint java_response_position) {
if (!response_id)
return;
auto it = pending_responses_.find(response_id);
if (it == pending_responses_.end())
return;
uint8_t* response_data = static_cast<uint8_t*>(env->GetDirectBufferAddress(java_response_data));
std::vector<uint8_t> response = std::vector<uint8_t>(response_data, response_data + java_response_position);
auto message_response = std::move(it->second);
pending_responses_.erase(it);
message_response->Complete(std::make_unique<fml::DataMapping>(std::move(response)));
}
4.3 平臺返回數(shù)據(jù)回到dart
這里的Complete對應(yīng)的是在PlatformMessageResponseDart中养渴,flutter發(fā)送消息的過程中有定義,這個方法中對應(yīng)的callback方法在dart send方法的時候就有定義泛烙,這里再寫一遍:
Future<ByteData> _sendPlatformMessage(String channel, ByteData message) {
ui.window.sendPlatformMessage(channel, message, (ByteData reply) {
completer.complete(reply);
});
return completer.future;
}
最終執(zhí)行到這個閉包了理卑。Completer是一個工作流的狀態(tài)管理類,最開始的時候新建一個對象胶惰,接下來執(zhí)行future任務(wù)傻工,任務(wù)完成后執(zhí)行complete表示執(zhí)行完成霞溪。
執(zhí)行完成的時候孵滞,在MethodChannel的invokeMethod方法中就接收到了返回數(shù)據(jù):
flutter\lib\src\services\platform_channel.dart
Future<T> invokeMethod<T>(String method, [ dynamic arguments ]) async {
final ByteData result = await binaryMessenger.send(name,codec.encodeMethodCall(MethodCall(method, arguments)),);
if (result == null) {
throw MissingPluginException('No implementation found for method $method on channel $name');
}
final T typedResult = codec.decodeEnvelope(result);
return typedResult;
}
這里的codec是StandardMethodCodec類型,將返回的數(shù)據(jù)解碼就可以返回了鸯匹。最終也在我們自己的dart代碼中接收到返回數(shù)據(jù)了坊饶。