核心点
主要分为3个部分
- 启动Engine前的准备(Platform端
Android) - Engine的启动(创建DartVM、相关线程、初始化相关配置)
- Engine加载Dart产物,直到执行
main.dart中的main方法
给官方提交了相关PR给官方,支持engine异步初始化
Engine创建流程不是很合理,底层在做异步任务的时候,主线程会wait阻塞,非常影响体验。
flutter版本:1.12
启动流程
//初始化engine
FlutterEngien engine = new FlutterEngine(...);
//加载dart代码
engine.getDartExecutor().executeDartEntrypoint(...);分为2部分
- 初始化engine
- 加载、执行Dart代码
整体流程图如下
初始化的对象大概如下
初始化engine
/** Fully configurable {@code FlutterEngine} constructor. */
public FlutterEngine(..) {
//第一步: 加载flutter.so、assest下的资源(字体、debug模式的snapshot文件)
flutterLoader.startInitialization(context.getApplicationContext());
flutterLoader.ensureInitializationComplete(context, dartVmArgs);
//第二步: 核心初始化函数,在native创建dartVM、相关线程
attachToJni();
this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
this.dartExecutor.onAttachedToJNI();
//第3步:创建renderer,管理flutter到surface/texuteview 的纹理显示数据,在启动activity后,会和acitvity上的view关联
this.renderer = new FlutterRenderer(flutterJNI);
//注册各种channnel(键盘、系统事件监听)
xxxChannel = new xxxChannel();
this.platformViewsController.onAttachedToJNI();
if (automaticallyRegisterPlugins) {
//第5步:注册 pubspect.ymal 中依赖的plugin
registerPlugins();
}
}1、启动Engine前的准备
- 初始化vsync
- 将assest下flutter的资源copy到私有目录中
- load flutter.so
- 主线程wait等待结果
//FlutterLoader.java
startInitialization(){
//初始化vsync
VsyncWaiter
.getInstance((WindowManager)appContext.getSystemService(Context.WINDOW_SERVICE))
.init();
Callable<InitResult> initTask = new Callable<InitResult>() {
//会启动一个asynctask,将assest目录下的flutter资源copy到私有目录
ResourceExtractor resourceExtractor = initResources(appContext);
System.loadLibrary("flutter");
//等待资源copy完毕
if (resourceExtractor != null) {
resourceExtractor.waitForCompletion();
}
};
initResultFuture = Executors.newSingleThreadExecutor().submit(initTask);
}主线程wait, 等待整个流程执行完成
flutterLoader.ensureInitializationComplete(...);2、启动engine
核心函数attachToJni(),辗转调用到AndroidShellHolder的构造函数中
AndroidShellHolder::AndroidShellHolder(...) {
//创建3个线程:UI、GPU、IO
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
ThreadHost::Type::IO};
//创建callback: platform_view_android
Shell::CreateCallback<PlatformView> on_create_platform_view = [](..) {
platform_view_android = std::make_unique<PlatformViewAndroid>(...);
);
//创建callback: Rasterizer
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
};
//创建callback: IOManager
fml::TaskRunner::RunNowOrPostTask(io_task_runner,[]() {
auto io_manager = std::make_unique<ShellIOManager>(...);
io_manager_promise.set_value(std::move(io_manager));
});
//创建engine(内部创建dart、skia环境)
shell_ =
Shell::Create(task_runners, // task runners
GetDefaultWindowData(), // window data
settings_, // settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
is_valid_ = shell_ != nullptr;
}主要是在初始化flutterengine运行的环境
- 3个线程(UI、GPU、IO)
- 创建3个callback: 用于初始化platform_view_android、Rasterizer、IOManager
- 创建engine
继续往下看
//shell.cc
std::unique_ptr<Shell> Shell::Create(){
//创建DartVm
auto vm = DartVMRef::Create(settings);
//创建engine
return Shell::Create(... , std::move(vm));
}首先,会创建一个DartVM,然后调用Shell::Create,内部会调用到函数CreateShellOnPlatformThread上
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(...) {
//创建shell对象,但是还未初始化完成
auto shell = std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));
//在gpu线程中创建rasterizer,用于将渲染结果,纹理化
fml::TaskRunner::RunNowOrPostTask(RasterTaskRunner, [..]() {
std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
rasterizer_promise.set_value(std::move(rasterizer));
});
//创建platformview对象
auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return nullptr;
}
//在io线程中创建IOManager,一般是用于图片纹理上传
fml::TaskRunner::RunNowOrPostTask(io_task_runner,[]() {
auto io_manager = std::make_unique<ShellIOManager>(...);
io_manager_promise.set_value(std::move(io_manager));
});
std::promise<std::unique_ptr<Engine>> engine_promise;
auto engine_future = engine_promise.get_future();
//创建native的engine对象
fml::TaskRunner::RunNowOrPostTask(UITaskRunner(),[...]() mutable {
//创建animator
auto animator = std::make_unique<Animator>(*shell, ...));
//创建engine
engine_promise.set_value(
std::make_unique<Engine>(weak_io_future.get(),...)
)
);
//主线程等待io、gpu、io线程的任务都执行完,完成对shell的初始化
if (!shell->Setup(std::move(platform_view), //
engine_future.get(), //
rasterizer_future.get(), //
io_manager_future.get()) //
) {
return nullptr;
}
return shell;
}分为3个部分
- 使用上一步的callback,创建相应的对象
- 在gpu线程中创建rasterizer
- 在platform线程中创建platform_view
- 在io线程中创建IOManager
- UI线程等待其它线程task执行完,开始创建engine
- platform线程wait(future.get),等待其它线程都执行完,最后执行
shell->Setup完成shell的初始化
这里其实设计的不是很好,在Android和iOS上阻塞主线程的代价是非常大的,测试低端机这里大概会有200ms左右的阻塞,已经给官方提了PR改成异步模式
我们接着看Engine的初始化
class Engine{
FontCollection font_collection_;
}
Engine::Engine(...) {
runtime_controller_ = std::make_unique<RuntimeController>(...);
}- 先初始化engine上的成员
FontCollection,这里也是一个比较耗时的地方 - engine的构造函数中,会去创建RuntimeController
RuntimeController::RuntimeController(...){
auto strong_root_isolate = DartIsolate::CreateRootIsolate(...).lock();
window->DidCreateIsolate();
}RuntimeController中会创建一个DartIsolate
DartIsolate图.jpg
std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(...) {
auto isolate_group_data = std::make_unique<std::shared_ptr<DartIsolateGroupData>>(
std::shared_ptr<DartIsolateGroupData>(new DartIsolateGroupData(...))
);
auto isolate_data = std::make_unique<std::shared_ptr<DartIsolate>>(
std::shared_ptr<DartIsolate>(new DartIsolate(...))
);
Dart_Isolate vm_isolate = CreateDartIsolateGroup(...);
std::shared_ptr<DartIsolate>* root_isolate_data =
static_cast<std::shared_ptr<DartIsolate>*>(Dart_IsolateData(vm_isolate));
(*root_isolate_data)->SetWindow(std::move(window));
return (*root_isolate_data)->GetWeakIsolatePtr();
}在执行完后,shel->DartVM->engine->runtimecontroller->DartIsolate的创建。回到CreateShellOnPlatformThread方法中
fml::TaskRunner::RunNowOrPostTask(UITaskRunner(),[...]() mutable {
//创建完shell后,通知platfrom线程
engine_promise.set_value(
std::make_unique<Engine>(weak_io_future.get(),...)
)
);
//platfrom线程线程等待io、gpu、io线程的任务都执行完,完成对shell的初始化
shell->Setup( ... , engine_future.get())
shell->Setup其实就是将上述执创建的engine、platform_view、rasterizer、io_manager等等挂到shell的成员变量上.
至此,native环境创建完毕,回到创建AndroidShellHolder的JNI函数attachjni入口
//platform_view_android_jni.cc
static jlong AttachJNI(...) {
auto shell_holder = std::make_unique<AndroidShellHolder>(...);
//返回AndroidShellHolder的指针
return reinterpret_cast<jlong>(shell_holder.release());
}
//FlutterJNI.java
public void attachToNative(boolean isBackgroundView) {
//持有AndroidShellHolder的指针
nativePlatformViewId = nativeAttach(this, isBackgroundView);
}FlutterJNI持有了AndroidshellHolder的指针,AndroidShellHolder持有了底层整个环境的变量(engine、shell、DartVm、DartIsolaate)
3、初始化变量
在attachToJni执行完后,会在平台层(Android)继续初始化上层需要的变量
//FlutterEngine.java
attachToJni()
//初始化DartExecutor,用于后面加载、执行dart产物
this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
this.dartExecutor.onAttachedToJNI();
//创建renderer,管理flutter到surface/texuteview 的纹理显示数据,在启动activity后,会和acitvity上的view关联
this.renderer = new FlutterRenderer(flutterJNI);
//注册各种channnel(键盘、系统事件监听)
xxxChannel = new xxxChannel();
//注册 pubspect.ymal 中依赖的plugin
if (automaticallyRegisterPlugins) {
registerPlugins();
}这里主要是在初始化上层的一些环境
- DartExecutor:用于后面加载、执行dart产物
- FlutterRenderer:管理flutter到surface/texuteview 的纹理显示数据,在启动activity后,会和acitvity上的view关联
- xxxChannel:各种flutter和native通信能力,比如监听系统事件的、activity切换声明周期等等
- registerPlugins: 注册注册
pubspect.ymal中依赖的plugin
private void registerPlugins() {
Class<?> generatedPluginRegistrant =
Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method registrationMethod =
generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
registrationMethod.invoke(null, this);
}反射调用GeneratedPluginRegistrant类,注册pubspect.ymal中声明的插件
加载执行Dart代码
接着看engine初始化完后,加载执行dart代码的流程
engine.getDartExecutor().executeDartEntrypoint(...);
//DartExecutor.java
executeEntryPoint(...){
flutterJNI.runBundleAndSnapshotFromLibrary(...);
}经过一系列跳转,最终会执行到DartIsolate的Run 函数
bool DartIsolate::Run(const std::string& entrypoint_name,
const std::vector<std::string>& args,
const fml::closure& on_run) {
//entrypoint_name为"main",指Dart代码的入口函数
//在dart产物上,寻找key为"main"(entrypoint_name)的入口函数
auto user_entrypoint_function =
Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));
auto entrypoint_args = tonic::ToDart(args);
//执行main.dart函数中的main()方法
if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
return false;
}
return true;
}最后
至此,flutter初始化完毕
- 可以正常执行dart代码
- 进行渲染(startActivity后)