Flutter应用启动流程分析(三)
在创建FlutterView时首先创建了FlutterNativeView,这里先看看FlutterNativeView是怎么创建的;
FlutterNativeView实现了BinaryMeeenger接口,下面看一下都有哪些属性
private final FlutterPluginRegistry mPluginRegistry;
private final DartExecutor dartExecutor;
private FlutterView mFlutterView;
private final FlutterJNI mFlutterJNI;
private final Context mContext;
private boolean applicationIsRunning;
FlutterPluginRegistry:实现了PluginRegistry的全部接口,管理Plugin的注册与注销的类。
DartExecutor:平台层与dart层交互执行类, 实现了平台向dart调用, dart向平台的响应功能.
FlutterView:这里保存的引用,主要是将底层的渲染与执行周期状态通知给FlutterView。
FlutterJNI:这个类是调用底层本地方法的, JNI的调用都在这里。
接着看构造方法
public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
mFlutterJNI = new FlutterJNI();
mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this, isBackgroundView);
assertAttached();
}
首先对mPluginRegistry、mFlutterJNI、dartExecutor进行了创建初始化,然后将两个回调事件设置给FlutterJNI的两个成员变量。Flutter engine在Surface执行渲染操作(渲染第一帧,停止渲染)和Flutter engine的生命周期变化会调用到FlutterJNI的相关方法,然后可通知设置的事件监听成员变量执行回调。
然后调用了attach方法
private void attach(FlutterNativeView view, boolean isBackgroundView) {
mFlutterJNI.attachToNative(isBackgroundView);
dartExecutor.onAttachedToJNI();
}
调用FlutterJNI的方法,最终调用了native的方法获得了一个nativePlatformViewId的底层指针引用。将FlutterJNI和Flutter native engine互相关联在一起进行双向通讯。
调用DartExecutor的onAttachedToJNI方法
public void onAttachedToJNI() {
Log.v(TAG, "Attached to JNI. Registering the platform message handler for this Dart execution context.");
flutterJNI.setPlatformMessageHandler(dartMessenger);
}
也是调用了FlutterJNI方法,设置DartMessenger给FlutterJNI的成员变量platformMessageHandler,通过此回调来响应Flutter native engine发过来的消息,最终交给DartMessenger来处理。DartMessenger是DartExecutor的成员变量,下边看看DartExecutor
DartExecutor
平台层与dart层交互执行类, 实现了BinaryMessenger接口,执行平台层向dart调用, dart向平台的响应功能.
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);
}
FlutterJNI:跟Flutter native engine交互;
AssetManager:传递给Flutter native engine使用;
DartMessenger:Android和Dart之间双向通信的消息管道,并初始设置了flutter/isolate消息通道处理响应类—BinaryMessageHandler。
BinaryMessenger:DartExecutor的内部类,同样实现了BinaryMessenger,DartExecutor的BinaryMessenger接口实现都转交给了这个内部类来处理。
DartExecutor有三个静态类两个公开的一个私有的,大体看一下
DartEntrypoint
公开的静态类,封装了调起Dart的相关参数:
pathToBundle:Flutter资源在应用中的路径
dartEntrypointFunctionName:要执行的Dart函数的名称
public DartEntrypoint(
@NonNull String pathToBundle,
@NonNull String dartEntrypointFunctionName
) {
this.pathToBundle = pathToBundle;
this.dartEntrypointFunctionName = dartEntrypointFunctionName;
}
DartCallback
公开静态类,同样封装了调起Dart的相关参数,指定执行哪个Dart函数,以及在何处查找执行Dart的函数和其他资源。
public DartCallback(
@NonNull AssetManager androidAssetManager,
@NonNull String pathToBundle,
@NonNull FlutterCallbackInformation callbackHandle
) {
this.androidAssetManager = androidAssetManager;
this.pathToBundle = pathToBundle;
this.callbackHandle = callbackHandle;
}
androidAssetManager:AssetManager
pathToBundle:Flutter资源在应用中的路径
callbackHandle:FlutterCallbackInformation封装类,成员变量有指定Dart的执行函数与lib库路径。
DefaultBinaryMessenger
私有静态类,实现了BinaryMessenger接口,DartExecutor实现的BinaryMessenger接口方法转交到这里实现,上边介绍属性事提到过
private static class DefaultBinaryMessenger implements BinaryMessenger {
private final DartMessenger messenger;
private DefaultBinaryMessenger(@NonNull DartMessenger messenger) {
this.messenger = messenger;
}
@Override
@UiThread
public void send(@NonNull String channel, @Nullable ByteBuffer message) {
messenger.send(channel, message, null);
}
@Override
@UiThread
public void send(@NonNull String channel, @Nullable ByteBuffer message, @Nullable BinaryMessenger.BinaryReply callback) {
messenger.send(channel, message, callback);
}
@Override
@UiThread
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessenger.BinaryMessageHandler handler) {
messenger.setMessageHandler(channel, handler);
}
}
三个方法实现最终调用到DartMessenger类中,这个类封装了全部处理Android与dart交互的消息。
现在看看BinaryMessenger接口,定义了原生平台与dart进行通信的方法。
public interface BinaryMessenger {
@UiThread
void send(@NonNull String channel, @Nullable ByteBuffer message);
@UiThread
void send(@NonNull String channel, @Nullable ByteBuffer message, @Nullable BinaryReply callback);
@UiThread
void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHandler handler);
interface BinaryMessageHandler {
@UiThread
void onMessage(@Nullable ByteBuffer message, @NonNull BinaryReply reply);
}
interface BinaryReply {
@UiThread
void reply(@Nullable ByteBuffer reply);
}
}
两个send方法时发给dart的,BinaryReply 回调可以在调用完dart后接收dart端的响应。
setMessageHandler:注册一个回调,flutter应用程序向原生平台发送消息时调用,当收到Flutter发送过来的数据时,通过BinaryMessageHandler接口进行响应。
回到DartMessenger看看怎么实现的交互(原生与dart层)
DartMessenger
Android和Dart之间双向通信的消息管道。
@NonNull
private final FlutterJNI flutterJNI;
@NonNull
private final Map<String, BinaryMessenger.BinaryMessageHandler> messageHandlers;
@NonNull
private final Map<Integer, BinaryMessenger.BinaryReply> pendingReplies;
private int nextReplyId = 1;
DartMessenger(@NonNull FlutterJNI flutterJNI) {
this.flutterJNI = flutterJNI;
this.messageHandlers = new HashMap<>();
this.pendingReplies = new HashMap<>();
}
flutterJNI上面已经介绍过了,看看这两个map集合是做什么的:
messageHandlers:
@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);
}
}
这个集合是缓存dart端调用android端的回调的,key为android端注册时传入的唯一标识名称,dart端调用时会只等此值来查找要调用的原生方法。BinaryMessageHandler处理dart端的调用。
pendingReplies:
@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 并且将callback添加到pendingReplies中, 否则传0。最终调用flutterJNI来发送消息给dart,在dart有返回值返回时会根据replyId获取到callback回调来处理消息。
@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);
}
}
handleMessageFromDart方法通过FlutterJni接受dart的调用,根据channel参数回调至指定的原生方法。
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);
}
}
}
handlePlatformMessageResponse方法通过FlutterJni接受dart端返回值处理的调用,根据replyId参数回调至指定的原生方法。
分析玩与FlutterNativeView相关的类后接着回到FlutterNativeView继续看其他的几个方法
public void runFromBundle(FlutterRunArguments args) {
if (args.entrypoint == null) {
throw new AssertionError("An entrypoint must be specified");
}
assertAttached();
if (applicationIsRunning)
throw new AssertionError(
"This Flutter engine instance is already running an application");
mFlutterJNI.runBundleAndSnapshotFromLibrary(
args.bundlePath,
args.entrypoint,
args.libraryPath,
mContext.getResources().getAssets()
);
applicationIsRunning = true;
}
主要检查了一下传入的参数,必须传递bundle的entrypoint ,最终调用FlutterJNI让Engine来运行Flutter bundle。Flutter就会开始执行Dart程序。复制变量applicationIsRunning标记已经执行。
FlutterNativeView实现的BinaryMessenger接口的三个方法交给了DartExecutor来处理,DartExecutor中又转交给了DartMessenger处理,最终两个send方法由FlutterJNI调用至Dart层。另外一个方法setMessageHandler由DartMessenger处理了。
总结:
由以上可知:
1、FlutterNativeView内部有一个DartExecutor,它负责跟Flutter Engine通信;
2、DartExecutor内部有FlutterNativeView初始化时传入的FlutterJNI,它负责调用Flutter Engine的C++代码。
3、DartExecutor内部有一个DartMessenger,他负责原生与Dart的消息通讯,这是由外层层层转发最终调用到DartMessenger然后再交给内部关联的FlutterJNI进行通讯的。
3、Dart应用的执行也是由FlutterNativeView调用FlutterJNI的本地方法来执行的。
可见处处离不开FlutterJNI,一个重要的类。