MethodChannel:用於雙向的方法呼叫,包括呼叫另一端的方法、響應另一端的呼叫,流程與 BasicMessageChannel
類似,只是資料轉換上略有不同,呼叫另一端的方法使用invokeMethod
函式,setMethodCallHandler
用於註冊一個MessageHandler
來供 Native 端呼叫
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;
}
invokeMethod
有兩個引數,方法名和方法要代入的引數,在 MethodCannel
中這兩個引數會被封裝成 MethodCall
物件,然後利用對應的 MethodCodec
將 MethodCall
編碼成 ByteData 傳遞到 binaryMessenger
,並得到 ByteData 型別的返回值,後面再利用 MethodCodec
將其解碼成泛型 T 類型資料
MethodCodec
相對於MessageCode
多了兩個函式,分別用於編解碼MethodCall
和編解碼方法呼叫的返回值
setMethodCallHandler
用於向 binaryMessenger 用於註冊一個MessageHandler
來供 Native 端呼叫
void setMethodCallHandler(Future<dynamic> handler(MethodCall call)) {
binaryMessenger.setMessageHandler(
name,
handler == null ? null : (ByteData message) => _handleAsMethodCall(message, handler),
);
}
Future<ByteData> _handleAsMethodCall(ByteData message, Future<dynamic> handler(MethodCall call)) async {
final MethodCall call = codec.decodeMethodCall(message);
try {
return codec.encodeSuccessEnvelope(await handler(call));
} on PlatformException catch (e) {
return codec.encodeErrorEnvelope(
code: e.code,
message: e.message,
details: e.details,
);
} on MissingPluginException {
return null;
} catch (e) {
return codec.encodeErrorEnvelope(code: 'error', message: e.toString(), details: null);
}
}
它會將 handler 封裝到 callback 函式中,在 _handleAsMethodCall
中進行協調,也就是先把 message 轉成 MethodCall
物件之後,再交給 handler 處理,處理完的結果再由 codec 轉成 ByteData 並返回,接著 binaryMessenger 再拿著這個資料回傳到 Native 端