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,一个重要的类。