通過上文分析,我們知道FlutterViewHandlePlatformMessage()實(shí)際上是通過JNI的方式最終調(diào)用了FlutterJNI.java中的handlePlatformMessage()方法,該方法接受三個(gè)來自Native層的參數(shù):
- channel: String類型,表示Channel名稱.
- message: 字節(jié)數(shù)組,表示方法調(diào)用中的數(shù)據(jù),如方法名和參數(shù).
- replyId: int類型,在將此次調(diào)用的響應(yīng)數(shù)據(jù)從Java層寫回到Native層時(shí)用到
public class FlutterJNI {
private PlatformMessageHandler platformMessageHandler;
@UiThread
public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformMessageHandler) {
this.platformMessageHandler = platformMessageHandler;
}
// Called by native.
@SuppressWarnings("unused")
private void handlePlatformMessage(final String channel, byte[] message, final int replyId) {
if (platformMessageHandler != null) {
platformMessageHandler.handleMessageFromDart(channel, message, replyId);
}
}
}
FlutterJNI類定義了Java層和Flutter C/C++引擎之間的相關(guān)接口.此類目前處于實(shí)驗(yàn)性質(zhì),隨著后續(xù)的發(fā)展可能會被不斷的重構(gòu)和優(yōu)化,不保證一直存在,不建議開發(fā)者調(diào)用該類.
為了建立Android應(yīng)用和Flutter C/C++引擎的連接,需要創(chuàng)建FlutterJNI實(shí)例,然后將其attach到Native,常見的使用方法如下:
// 1.創(chuàng)建FlutterJNI實(shí)例
FlutterJNI flutterJNI = new FlutterJNI();
// 2.建立和Native層的連接
flutterJNI.attachToNative();
......
// 3.斷開和Native層的連接,并釋放資源
flutterJNI.detachFromNativeAndReleaseResources();
FlutterJNI中handlePlatformMessage()
,在該方法中首先判斷platformMessageHandler是否為null,不為null,則調(diào)用其handleMessageFromDart()
方法.其中platformMessageHandler需要通過FlutterJNI中的setPlatformMessageHandler()
方法來設(shè)置.在FlutterNativeView中調(diào)用的。
public class FlutterNativeView implements BinaryMessenger {
private final Map<String, BinaryMessageHandler> mMessageHandlers;
private int mNextReplyId = 1;
private final Map<Integer, BinaryReply> mPendingReplies = new HashMap<>();
private final FlutterPluginRegistry mPluginRegistry;
private FlutterView mFlutterView;
private FlutterJNI mFlutterJNI;
private final Context mContext;
private boolean applicationIsRunning;
public FlutterNativeView(Context context, boolean isBackgroundView) {
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
// 創(chuàng)建FlutterJNI實(shí)例
mFlutterJNI = new FlutterJNI();
mFlutterJNI.setRenderSurface(new RenderSurfaceImpl());
// 將PlatformMessageHandlerImpl實(shí)例賦值給FlutterJNI中的platformMessageHandler屬性
mFlutterJNI.setPlatformMessageHandler(new PlatformMessageHandlerImpl());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this, isBackgroundView);
assertAttached();
mMessageHandlers = new HashMap<>();
}
.......
}
在FlutterNativeView的構(gòu)造函數(shù)中,首先創(chuàng)建FlutterJNI實(shí)例mFlutterJNI,然后調(diào)用setPlatformMessageHandler()
并把PlatformMessageHandlerImpl實(shí)例作為參數(shù)傳入.因此在FlutterJNI的handlePlatformMessage()
方法中,最終調(diào)用PlatformMessageHandlerImpl實(shí)例的handleMessageFromDart()
來處理來自Flutter中的消息.
public class FlutterNativeView implements BinaryMessenger {
private final Map<String, BinaryMessageHandler> mMessageHandlers;
......
private final class PlatformMessageHandlerImpl implements PlatformMessageHandler {
// Called by native to send us a platform message.
public void handleMessageFromDart(final String channel, byte[] message, final int replyId) {
// 1.根據(jù)channel名稱獲取對應(yīng)的BinaryMessageHandler對象.每個(gè)Channel對應(yīng)一個(gè)Handler對象
BinaryMessageHandler handler = mMessageHandlers.get(channel);
if (handler != null) {
try {
// 2.將字節(jié)數(shù)組對象封裝為ByteBuffer對象
final ByteBuffer buffer = (message == null ? null : ByteBuffer.wrap(message));
// 3.調(diào)用handler對象的onMessage()方法來分發(fā)消息
handler.onMessage(buffer, new BinaryReply() {
private final AtomicBoolean done = new AtomicBoolean(false);
@Override
public void reply(ByteBuffer reply) {
// 4.根據(jù)reply的情況,調(diào)用FlutterJNI中invokePlatformMessageXXX()方法將響應(yīng)數(shù)據(jù)發(fā)送給Flutter層
if (reply == null) {
mFlutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
} else {
mFlutterJNI.invokePlatformMessageResponseCallback(replyId, reply, reply.position());
}
}
});
} catch (Exception exception) {
mFlutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
}
return;
}
mFlutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
}
}
以Channel名稱作為key,以BinaryMessageHandler類型為value.在handleMessageFromDart()
方法中,首先根據(jù)Channel名稱從mMessageHandlers取出對應(yīng)的二進(jìn)制消息處理器BinaryMessageHandler,然后將字節(jié)數(shù)組message封裝為ByteBuffer對象,然后調(diào)用BinaryMessageHandler實(shí)例的onMessage()
方法處理ByteBuffer,并進(jìn)行響應(yīng).
BinaryReply是一個(gè)接口,主要用來將ByteBuffer類型的響應(yīng)數(shù)據(jù)reply從Java層寫回到Flutter層.根據(jù)reply是否為null,調(diào)用FlutterJNI實(shí)例不同的方法.
BinaryMessageHandler是如何添加到mMessageHandler中:
public class FlutterNativeView implements BinaryMessenger {
private final Map<String, BinaryMessageHandler> mMessageHandlers;
......
@Override
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
if (handler == null) {
mMessageHandlers.remove(channel);
} else {
mMessageHandlers.put(channel, handler);
}
}
.......
}
public class MainActivity extends FlutterActivity {
// 1.定義Channel的名稱,該名稱作為Channel的唯一標(biāo)識符
private static final String CHANNEL = "samples.flutter.io/battery";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 2.創(chuàng)建MethodChannel對象channel
MethodChannel channel = new MethodChannel(getFlutterView(), CHANNEL);
// 3.調(diào)用MethodChannel實(shí)例的setMethodCallHandler()方法為當(dāng)前channel設(shè)置Handler
channel.setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
// TODO
}
});
}
}
接下來是 MethodChannel 定義
public final class MethodChannel {
// 二進(jìn)制信使
private final BinaryMessenger messenger;
// Channel名稱
private final String name;
// 方法編碼
private final MethodCodec codec;
public MethodChannel(BinaryMessenger messenger, String name) {
this(messenger, name, StandardMethodCodec.INSTANCE);
}
public MethodChannel(BinaryMessenger messenger, String name, MethodCodec codec) {
assert messenger != null;
assert name != null;
assert codec != null;
this.messenger = messenger;
this.name = name;
this.codec = codec;
}
......
public void setMethodCallHandler(final @Nullable MethodCallHandler handler) {
messenger.setMessageHandler(name,
handler == null ? null : new IncomingMethodCallHandler(handler));
}
......
private final class IncomingMethodCallHandler implements BinaryMessageHandler {
private final MethodCallHandler handler;
IncomingMethodCallHandler(MethodCallHandler handler) {
this.handler = handler;
}
@Override
public void onMessage(ByteBuffer message, final BinaryReply reply) {
// 1.使用codec對來自Flutter方法調(diào)用數(shù)據(jù)進(jìn)行解碼,并將其封裝為MethodCall對象.
// MethodCall中包含兩部分?jǐn)?shù)據(jù):method表示要調(diào)用的方法;arguments表示方法所需參數(shù)
final MethodCall call = codec.decodeMethodCall(message);
try {
// 2.調(diào)用自定義MethodCallHandler中的onMethodCall方法繼續(xù)處理方法調(diào)用
handler.onMethodCall(call, new Result() {
@Override
public void success(Object result) {
// 調(diào)用成功時(shí),需要回傳數(shù)據(jù)給Flutter層時(shí),使用codec對回傳數(shù)據(jù)result
// 進(jìn)行編碼
reply.reply(codec.encodeSuccessEnvelope(result));
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
// 調(diào)用失敗時(shí),需要回傳錯(cuò)誤數(shù)據(jù)給Flutter層時(shí),使用codec對errorCode,
// errorMessage,errorDetails進(jìn)行編碼
reply.reply(codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails));
}
@Override
public void notImplemented() {
// 方法沒有實(shí)現(xiàn)時(shí),調(diào)用該方法后,flutter將會受到相應(yīng)的錯(cuò)誤消息
reply.reply(null);
}
});
} catch (RuntimeException e) {
Log.e(TAG + name, "Failed to handle method call", e);
reply.reply(codec.encodeErrorEnvelope("error", e.getMessage(), null));
}
}
}
}
在上述代碼中,首先使用codec對來自Flutter層的二進(jìn)制數(shù)據(jù)進(jìn)行解碼,并將其封裝為MethodCall對象,然后調(diào)用MethodCallHandler.onMethodCall()
方法.
Java->Native
public class FlutterJNI {
private Long nativePlatformViewId;
......
@UiThread
public void invokePlatformMessageResponseCallback(int responseId, ByteBuffer message, int position) {
// 1.檢查FlutterJNI是否已經(jīng)attach到Native層,如若沒有則拋出異常
ensureAttachedToNative();
// 2.繼續(xù)調(diào)用nativeInvokePlatformMessageResponseCallback()
nativeInvokePlatformMessageResponseCallback(
nativePlatformViewId,
responseId,
message,
position
);
}
private native void nativeInvokePlatformMessageResponseCallback(
long nativePlatformViewId,
int responseId,
ByteBuffer message,
int position
);
......
private void ensureAttachedToNative() {
// FlutterJNI attach到Native層后,會返回一個(gè)long類型的值用來初始化nativePlatformViewId
if (nativePlatformViewId == null) {
throw new RuntimeException("Cannot execute operation because FlutterJNI is not attached to native.");
}
}
}
當(dāng)數(shù)據(jù)需要寫回時(shí),數(shù)據(jù)首先通過codec被編碼成ByteBuffer類型,然后調(diào)用reply的reply()
方法.在reply()
方法中,對于非null類型的ByteBuffer,會調(diào)用FlutterJNI中的invokePlatformMessageResponseCallback()
.
在上述invokePlatformMessageResponseCallback()
方法中,首先檢查當(dāng)前FlutterJNI實(shí)例是否已經(jīng)attach到Native層,然后調(diào)用Native方法nativeInvokePlatformMessageResponseCallback()
向JNI層寫入數(shù)據(jù)
void PlatformViewAndroid::InvokePlatformMessageResponseCallback(
JNIEnv* env,
jint response_id,
jobject java_response_data,
jint java_response_position) {
if (!response_id)
return;
// 1.通過response_id從pending_responses_中取出response
auto it = pending_responses_.find(response_id);
if (it == pending_responses_.end())
return;
// 2.GetDirectBufferAddress函數(shù)返回一個(gè)指向被傳入的ByteBuffer對象的地址指針
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);
// 3.從pending_responses_中移除該response
pending_responses_.erase(it);
// 4.調(diào)用response的Complete()方法將二進(jìn)制結(jié)果返回
message_response->Complete(
std::make_unique<fml::DataMapping>(std::move(response)));
}
Native -> Dart
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);
// 將Native層的二進(jìn)制數(shù)據(jù)data轉(zhuǎn)為Dart中的二進(jìn)制數(shù)據(jù)byte_buffer
Dart_Handle byte_buffer = WrapByteData(std::move(data));
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}