今天基于Android分析下Flutter的启动流程,首先看下官网提供的框架图,最下面一层Embedder是特定的平台实现,Android平台代码在engine/shell/platform/android下,其中有java的嫁接层在engine/shell/platform/android/io/flutter下面。Embedder层是Flutter启动的关键,在应用启动后通过该层初始化Flutter Engine,在Engine中会创建DartVM,在DartVM中执行dart编写的入口方法main方法,这样Flutter模块就启动成功。
1.Android平台代码分析
这部分代码是Embedder层的,在engine/shell/platform/android/io/flutter下面。
首先看到FlutterApplication中的onCreate
@CallSuper
public void onCreate() {
super.onCreate();
FlutterMain.startInitialization(this);
}
接着到FlutterMain中:
public static void startInitialization(Context applicationContext, FlutterMain.Settings settings) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
} else if (sSettings == null) {
sSettings = settings;
long initStartTimestampMillis = SystemClock.uptimeMillis();
initConfig(applicationContext);
initAot(applicationContext);
initResources(applicationContext);
System.loadLibrary("flutter");
long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
nativeRecordStartTimestamp(initTimeMillis);
}
}
在这里会进行配置信息初始化,初始化AOT模式或者JIT模式变量,资源文件初始化,主要是将asset目录下的flutter相关资源copy到私有目录下,看一个手机上私有目录下的截图
最后调用JNI方法nativeRecordStartTimestamp记录到C++层。
FlutterApplication执行完会执行MainActivity中的onCreate,主要工作会在父类FlutterActivity中,然后委托给FlutterActivityDelegate:
// FlutterActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.eventDelegate.onCreate(savedInstanceState);
}
// FlutterActivityDelegate
@Override
public void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(0x40000000);
window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI);
}
String[] args = getArgsFromIntent(activity.getIntent());
FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), args);
flutterView = viewFactory.createFlutterView(activity);
if (flutterView == null) {
FlutterNativeView nativeView = viewFactory.createFlutterNativeView();
flutterView = new FlutterView(activity, null, nativeView);
flutterView.setLayoutParams(matchParent);
activity.setContentView(flutterView);
launchView = createLaunchView();
if (launchView != null) {
addLaunchView();
}
}
if (loadIntent(activity.getIntent())) {
return;
}
String appBundlePath = FlutterMain.findAppBundlePath(activity.getApplicationContext());
if (appBundlePath != null) {
runBundle(appBundlePath);
}
}
可以看到有个setContentView,就是在这里设置内容视图,总结下FlutterActivityDelegate做的事:
1.根据系统版本设置状态栏样式
2.获取Intent
3.
FlutterMain.ensureInitializationComplete4.
create FlutterNativeView5.
create FlutterView6.设置activity的内容视图
7.执行
appBundlePath
前面2步没什么说的,从第3步开始看。
2.FlutterMain
public static void ensureInitializationComplete(Context applicationContext, String[] args) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
} else if (sSettings == null) {
throw new IllegalStateException("ensureInitializationComplete must be called after startInitialization");
} else if (!sInitialized) {
try {
sResourceExtractor.waitForCompletion();
List<String> shellArgs = new ArrayList();
shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
if (args != null) {
Collections.addAll(shellArgs, args);
}
if (sIsPrecompiledAsSharedLibrary) {
shellArgs.add("--aot-shared-library-path=" + new File(PathUtils.getDataDirectory(applicationContext), sAotSharedLibraryPath));
} else {
if (sIsPrecompiledAsBlobs) {
shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext));
} else {
shellArgs.add("--cache-dir-path=" + PathUtils.getCacheDirectory(applicationContext));
shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext) + "/" + sFlutterAssetsDir);
}
shellArgs.add("--vm-snapshot-data=" + sAotVmSnapshotData);
shellArgs.add("--vm-snapshot-instr=" + sAotVmSnapshotInstr);
shellArgs.add("--isolate-snapshot-data=" + sAotIsolateSnapshotData);
shellArgs.add("--isolate-snapshot-instr=" + sAotIsolateSnapshotInstr);
}
if (sSettings.getLogTag() != null) {
shellArgs.add("--log-tag=" + sSettings.getLogTag());
}
String appBundlePath = findAppBundlePath(applicationContext);
String appStoragePath = PathUtils.getFilesDir(applicationContext);
String engineCachesPath = PathUtils.getCacheDirectory(applicationContext);
nativeInit(applicationContext, (String[])shellArgs.toArray(new String[0]), appBundlePath, appStoragePath, engineCachesPath);
sInitialized = true;
} catch (Exception var6) {
Log.e("FlutterMain", "Flutter initialization failed.", var6);
throw new RuntimeException(var6);
}
}
}
该方法必须要在主线程中执行并且只执行一次。并且要等sResourceExtractor把资源copy到安装包目录下完成后才能往下继续:
sResourceExtractor.waitForCompletion();
void waitForCompletion() {
if (this.mExtractTask != null) {
try {
this.mExtractTask.get();
} catch (ExecutionException | InterruptedException | CancellationException var2) {
this.deleteFiles();
}
}
}
private class ExtractTask extends AsyncTask<Void, Void, Void> {...}
那么拷贝的是哪些东西呢?看一个debug下的apk:
其中vm开头的是dartvm执行需要的,isolate就是我们用dart语言编写的业务代码。
看下release包的apk,和debug有点不一样,多出了几个文件。
再回到之前的代码那里,就是把assets目录下的这些文件拷贝到安装包私有目录下的flutter_assets.
代码里面有很多的路径名:
private static final String DEFAULT_KERNEL_BLOB = "kernel_blob.bin";
private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets";
private static String sAotSharedLibraryPath = "app.so";
private static String sAotVmSnapshotData = "vm_snapshot_data";
private static String sAotVmSnapshotInstr = "vm_snapshot_instr";
private static String sAotIsolateSnapshotData = "isolate_snapshot_data";
private static String sAotIsolateSnapshotInstr = "isolate_snapshot_instr";
private static String sFlx = "app.flx";
private static String sFlutterAssetsDir = "flutter_assets";
接着会初始化一些目录,包括appBundle路径,应用存储目录,引擎缓存目录等。然后会调用JNI方法nativeInit在C++层初始化这些信息,在FlutterMain中把这些路径设置给setting,然后传递构造FlutterMain,再保存到全局变量g_flutter_main中。
// shell/platform/android/flutter_main.cc
static std::unique_ptr<FlutterMain> g_flutter_main;
void FlutterMain::Init(JNIEnv* env,
jclass clazz,
jobject context,
jobjectArray jargs,
jstring bundlePath,
jstring appStoragePath,
jstring engineCachesPath) {
std::vector<std::string> args;
args.push_back("flutter");
for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
args.push_back(std::move(arg));
}
auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
auto settings = SettingsFromCommandLine(command_line);
settings.assets_path = fml::jni::JavaStringToString(env, bundlePath);
// Restore the callback cache.
// TODO(chinmaygarde): Route all cache file access through FML and remove this
// setter.
blink::DartCallbackCache::SetCachePath(
fml::jni::JavaStringToString(env, appStoragePath));
fml::paths::InitializeAndroidCachesPath(
fml::jni::JavaStringToString(env, engineCachesPath));
blink::DartCallbackCache::LoadCacheFromDisk();
if (!blink::DartVM::IsRunningPrecompiledCode()) {
// Check to see if the appropriate kernel files are present and configure
// settings accordingly.
auto application_kernel_path =
fml::paths::JoinPaths({settings.assets_path, "kernel_blob.bin"});
if (fml::IsFile(application_kernel_path)) {
settings.application_kernel_asset = application_kernel_path;
}
}
settings.task_observer_add = [](intptr_t key, fml::closure callback) {
fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
};
settings.task_observer_remove = [](intptr_t key) {
fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
};
...
// Not thread safe. Will be removed when FlutterMain is refactored to no
// longer be a singleton.
g_flutter_main.reset(new FlutterMain(std::move(settings)));
}
接着看上面第四部create FlutterNativeView.
3.FlutterNativeView
public FlutterNativeView(Context context, boolean isBackgroundView) {
this.mNextReplyId = 1;
this.mPendingReplies = new HashMap();
this.mContext = context;
this.mPluginRegistry = new FlutterPluginRegistry(this, context);
this.mFlutterJNI = new FlutterJNI();
this.mFlutterJNI.setRenderSurface(new FlutterNativeView.RenderSurfaceImpl());
this.mFlutterJNI.setPlatformMessageHandler(new FlutterNativeView.PlatformMessageHandlerImpl());
this.mFlutterJNI.addEngineLifecycleListener(new FlutterNativeView.EngineLifecycleListenerImpl());
this.attach(this, isBackgroundView);
this.assertAttached();
this.mMessageHandlers = new HashMap();
}
其中FlutterJNI是Java层和Flutter Engine通信的桥梁,包括创建并启动Flutter engine、当前FlutterView的Surface生命周期的通知、传递platform数据给dart层、回传dart层调用platform层方法返回的结果数据等待。
然后会调用attach方法:
// FlutterNativeView.java
private void attach(FlutterNativeView view, boolean isBackgroundView) {
this.mFlutterJNI.attachToNative(isBackgroundView);
}
// FlutterJNI.java
@UiThread
public void attachToNative(boolean isBackgroundView) {
this.ensureNotAttachedToNative();
this.nativePlatformViewId = this.nativeAttach(this, isBackgroundView);
}
attachToNative方法中通过调用JNI方法nativeAttach将当前flutterJNI对象传递给c++层(后续一些dart层调用java层的方法就是通过该对象调用对应的方法实现的),得到c++层返回的nativePlatformViewId,这个值非常重要,是c++层AndroidShellHolder的对象指针值,后续会通过该值调用一系列c++层的方法执行操作,并将其保存以供后续使用。
对应的C++方法如下, 通过之前初始化保存在g_flutter_main对象中的settings值和传入的java对象flutterJNI创建std::unique_ptr对象(该对象通过指针占有并管理AndroidShellHolder对象),该对象有效的情况下会调用release方法返回其管理对象的指针并释放对象的所有权,reinterpret_cast()方法将该AndroidShellHolder对象指针强制转化为long类型的值并返回java层保存。
// platform_view_android_jni.cc
// Called By Java
static jlong AttachJNI(JNIEnv* env,
jclass clazz,
jobject flutterJNI,
jboolean is_background_view) {
fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
auto shell_holder = std::make_unique<AndroidShellHolder>(
FlutterMain::Get().GetSettings(), java_object, is_background_view);
if (shell_holder->IsValid()) {
return reinterpret_cast<jlong>(shell_holder.release());
} else {
return 0;
}
}
接着看下很重要的一个类AndroiudShellHolder.
4.AndroiudShellHolder
代码比较长,先看下前半部分,传入的参数is_background_view为false,会首先通过ThreadHost初始化三个线程ui_thread,gpu_thread, io_thread,而当前线程就是platform_thread.
platform_thread负责和Engine层的通信io_thread负责IO操作gpu_thread执行GPU指令ui_thread执行Dart层isolate代码
// android_shell_holder.cc
AndroidShellHolder::AndroidShellHolder(
blink::Settings settings,
fml::jni::JavaObjectWeakGlobalRef java_object,
bool is_background_view)
: settings_(std::move(settings)), java_object_(java_object) {
static size_t shell_count = 1;
auto thread_label = std::to_string(shell_count++);
FML_CHECK(pthread_key_create(&thread_destruct_key_, ThreadDestructCallback) ==
0);
if (is_background_view) {
thread_host_ = {thread_label, ThreadHost::Type::UI};
} else {
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
ThreadHost::Type::IO};
}
...
}
四个线程会持有MessageLoop,通过他可以往线程添加工作任务, 具体可以参考另外一篇Flutter和原生之间的平台通道实践与原理的线程部分。接着会构造Shell:
// android_shell_holder.cc
blink::TaskRunners task_runners(thread_label, // label
platform_runner, // platform
gpu_runner, // gpu
ui_runner, // ui
io_runner // io
);
shell_ =
Shell::Create(task_runners, // task runners
settings_, // settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
// shell.cc
std::unique_ptr<Shell> Shell::Create(
blink::TaskRunners task_runners,
blink::Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
PerformInitializationTasks(settings);
TRACE_EVENT0("flutter", "Shell::Create");
auto vm = blink::DartVMRef::Create(settings);
FML_CHECK(vm) << "Must be able to initialize the VM.";
auto vm_data = vm->GetVMData();
return Shell::Create(std::move(task_runners), //
std::move(settings), //
vm_data->GetIsolateSnapshot(), // isolate snapshot
blink::DartSnapshot::Empty(), // shared snapshot
std::move(on_create_platform_view), //
std::move(on_create_rasterizer), //
std::move(vm) //
);
}
在Shell Create中会根据传入的settings参数通过blink::DartVMRef::Create构造Dart VM, 跟进去看看Dart VM的创建过程, VM只会构造一次,
// dart_vm_lifecycle.cc
DartVMRef DartVMRef::Create(Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot,
fml::RefPtr<DartSnapshot> shared_snapshot) {
std::lock_guard<std::mutex> lifecycle_lock(gVMMutex);
// If there is already a running VM in the process, grab a strong reference to
// it.
if (auto vm = gVM.lock()) {
FML_DLOG(WARNING) << "Attempted to create a VM in a process where one was "
"already running. Ignoring arguments for current VM "
"create call and reusing the old VM.";
// There was already a running VM in the process,
return DartVMRef{std::move(vm)};
}
std::lock_guard<std::mutex> dependents_lock(gVMDependentsMutex);
gVMData.reset();
gVMServiceProtocol.reset();
gVMIsolateNameServer.reset();
gVM.reset();
// If there is no VM in the process. Initialize one, hold the weak reference
// and pass a strong reference to the caller.
auto isolate_name_server = std::make_shared<IsolateNameServer>();
auto vm = DartVM::Create(std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
std::move(shared_snapshot), //
isolate_name_server //
);
if (!vm) {
FML_LOG(ERROR) << "Could not create Dart VM instance.";
return {nullptr};
}
gVMData = vm->GetVMData();
gVMServiceProtocol = vm->GetServiceProtocol();
gVMIsolateNameServer = isolate_name_server;
gVM = vm;
if (settings.leak_vm) {
gVMLeak = vm;
}
return DartVMRef{std::move(vm)};
}
然后通过DartVM::Create执行具体的构造过程,在Create中会调用DartVM构造函数, 通过执行dart::bin::BootstrapDartIo()方法引导启动dart:io时间处理程序:
//dart_vm.cc
DartVM::DartVM(std::shared_ptr<const DartVMData> vm_data,
std::shared_ptr<IsolateNameServer> isolate_name_server)
: settings_(vm_data->GetSettings()),
vm_data_(vm_data),
isolate_name_server_(std::move(isolate_name_server)),
service_protocol_(std::make_shared<ServiceProtocol>()) {
TRACE_EVENT0("flutter", "DartVMInitializer");
gVMLaunchCount++;
FML_DCHECK(vm_data_);
FML_DCHECK(isolate_name_server_);
FML_DCHECK(service_protocol_);
FML_DLOG(INFO) << "Attempting Dart VM launch for mode: "
<< (IsRunningPrecompiledCode() ? "AOT" : "Interpreter");
{
TRACE_EVENT0("flutter", "dart::bin::BootstrapDartIo");
dart::bin::BootstrapDartIo();
if (!settings_.temp_directory_path.empty()) {
dart::bin::SetSystemTempDirectory(settings_.temp_directory_path.c_str());
}
}
...
DartUI::InitForGlobal();
{
TRACE_EVENT0("flutter", "Dart_Initialize");
Dart_InitializeParams params = {};
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
params.vm_snapshot_data =
vm_data_->GetVMSnapshot().GetData()->GetSnapshotPointer();
params.vm_snapshot_instructions =
vm_data_->GetVMSnapshot().GetInstructionsIfPresent();
params.create = reinterpret_cast<decltype(params.create)>(
DartIsolate::DartIsolateCreateCallback);
params.shutdown = reinterpret_cast<decltype(params.shutdown)>(
DartIsolate::DartIsolateShutdownCallback);
params.cleanup = reinterpret_cast<decltype(params.cleanup)>(
DartIsolate::DartIsolateCleanupCallback);
params.thread_exit = ThreadExitCallback;
params.get_service_assets = GetVMServiceAssetsArchiveCallback;
params.entropy_source = DartIO::EntropySource;
char* init_error = Dart_Initialize(¶ms);
...
}
}
DartUI::InitForGlobal会注册dart的各种本地方法,主要用于dart调用c++层方法,有点类似于java中的jni注册:
// dart_ui.cc
void DartUI::InitForGlobal() {
if (!g_natives) {
g_natives = new tonic::DartLibraryNatives();
Canvas::RegisterNatives(g_natives);
CanvasGradient::RegisterNatives(g_natives);
CanvasImage::RegisterNatives(g_natives);
CanvasPath::RegisterNatives(g_natives);
CanvasPathMeasure::RegisterNatives(g_natives);
Codec::RegisterNatives(g_natives);
DartRuntimeHooks::RegisterNatives(g_natives);
EngineLayer::RegisterNatives(g_natives);
FontCollection::RegisterNatives(g_natives);
FrameInfo::RegisterNatives(g_natives);
ImageFilter::RegisterNatives(g_natives);
ImageShader::RegisterNatives(g_natives);
IsolateNameServerNatives::RegisterNatives(g_natives);
Paragraph::RegisterNatives(g_natives);
ParagraphBuilder::RegisterNatives(g_natives);
Picture::RegisterNatives(g_natives);
PictureRecorder::RegisterNatives(g_natives);
Scene::RegisterNatives(g_natives);
SceneBuilder::RegisterNatives(g_natives);
SceneHost::RegisterNatives(g_natives);
SemanticsUpdate::RegisterNatives(g_natives);
SemanticsUpdateBuilder::RegisterNatives(g_natives);
Versions::RegisterNatives(g_natives);
Vertices::RegisterNatives(g_natives);
Window::RegisterNatives(g_natives);
// Secondary isolates do not provide UI-related APIs.
g_natives_secondary = new tonic::DartLibraryNatives();
DartRuntimeHooks::RegisterNatives(g_natives_secondary);
IsolateNameServerNatives::RegisterNatives(g_natives_secondary);
}
}
// window.cc
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"Window_defaultRouteName", DefaultRouteName, 1, true},
{"Window_scheduleFrame", ScheduleFrame, 1, true},
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
{"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
{"Window_render", Render, 2, true},
{"Window_updateSemantics", UpdateSemantics, 2, true},
{"Window_setIsolateDebugName", SetIsolateDebugName, 2, true},
{"Window_reportUnhandledException", ReportUnhandledException, 2, true},
});
}
然后再DartVM中通过Dart_Initialize初始化Dart运行时环境,后面就不往下跟了,返回到shell.cc中,构造玩vm后会赋值给Shell, 再通过CreateShellOnPlatformThread构造Shell,该方法会在PlatformThread线程中执行。
std::unique_ptr<Shell> Shell::Create(
blink::TaskRunners task_runners,
blink::Settings settings,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer,
blink::DartVMRef vm) {
PerformInitializationTasks(settings);
TRACE_EVENT0("flutter", "Shell::CreateWithSnapshots");
if (!task_runners.IsValid() || !on_create_platform_view ||
!on_create_rasterizer) {
return nullptr;
}
fml::AutoResetWaitableEvent latch;
std::unique_ptr<Shell> shell;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetPlatformTaskRunner(),
fml::MakeCopyable([&latch, //
vm = std::move(vm), //
&shell, //
task_runners = std::move(task_runners), //
settings, //
isolate_snapshot = std::move(isolate_snapshot), //
shared_snapshot = std::move(shared_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
]() mutable {
shell = CreateShellOnPlatformThread(std::move(vm),
std::move(task_runners), //
settings, //
std::move(isolate_snapshot), //
std::move(shared_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
);
latch.Signal();
}));
latch.Wait();
return shell;
}
接下来到CreateShellOnPlatformThread看看,代码比较多分成几个部分来看, 首先调用new Shell构造,然后调用on_create_platform_view,这个方法在android_shell_holder.cc中通过Shell::Create传递过来的
// shell.cc
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
blink::DartVMRef vm,
blink::TaskRunners task_runners,
blink::Settings settings,
fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
if (!task_runners.IsValid()) {
FML_LOG(ERROR) << "Task runners to run the shell were invalid.";
return nullptr;
}
auto shell =
std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));
// Create the platform view on the platform thread (this thread).
auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return nullptr;
}
...
}
看下on_create_platform_view,在这里会构造PlatformViewAndroid并且交给platform_view管理
// android_shell_holder.cc
fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
Shell::CreateCallback<PlatformView> on_create_platform_view =
[is_background_view, java_object, &weak_platform_view](Shell& shell) {
std::unique_ptr<PlatformViewAndroid> platform_view_android;
if (is_background_view) {
platform_view_android = std::make_unique<PlatformViewAndroid>(
shell, // delegate
shell.GetTaskRunners(), // task runners
java_object // java object handle for JNI interop
);
} else {
platform_view_android = std::make_unique<PlatformViewAndroid>(
shell, // delegate
shell.GetTaskRunners(), // task runners
java_object, // java object handle for JNI interop
shell.GetSettings()
.enable_software_rendering // use software rendering
);
}
weak_platform_view = platform_view_android->GetWeakPtr();
return platform_view_android;
};
再回到shell.cc中接着往下看,接着会在IO Thread中构造IOManager对象并且交给io_manager管理:
// Create the IO manager on the IO thread. The IO manager must be initialized
// first because it has state that the other subsystems depend on. It must
// first be booted and the necessary references obtained to initialize the
// other subsystems.
fml::AutoResetWaitableEvent io_latch;
std::unique_ptr<IOManager> io_manager;
auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner();
fml::TaskRunner::RunNowOrPostTask(
io_task_runner,
[&io_latch, //
&io_manager, //
&platform_view, //
io_task_runner //
]() {
TRACE_EVENT0("flutter", "ShellSetupIOSubsystem");
io_manager = std::make_unique<IOManager>(
platform_view->CreateResourceContext(), io_task_runner);
io_latch.Signal();
});
io_latch.Wait();
接着会在GPU Thread中构造Rasterizer对象并且交给rasterizer管理,on_create_rasterizer也是在android_shell_holder.cc中通过Shell::Create传递过来的
// Create the rasterizer on the GPU thread.
fml::AutoResetWaitableEvent gpu_latch;
std::unique_ptr<Rasterizer> rasterizer;
fml::WeakPtr<blink::SnapshotDelegate> snapshot_delegate;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetGPUTaskRunner(), [&gpu_latch, //
&rasterizer, //
on_create_rasterizer, //
shell = shell.get(), //
&snapshot_delegate //
]() {
TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
if (auto new_rasterizer = on_create_rasterizer(*shell)) {
rasterizer = std::move(new_rasterizer);
snapshot_delegate = rasterizer->GetSnapshotDelegate();
}
gpu_latch.Signal();
});
gpu_latch.Wait();
接着在UIThread中创建Engine,并且交给engine管理:
// Create the engine on the UI thread.
fml::AutoResetWaitableEvent ui_latch;
std::unique_ptr<Engine> engine;
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
fml::MakeCopyable([&ui_latch, //
&engine, //
shell = shell.get(), //
isolate_snapshot = std::move(isolate_snapshot), //
shared_snapshot = std::move(shared_snapshot), //
vsync_waiter = std::move(vsync_waiter), //
snapshot_delegate = std::move(snapshot_delegate), //
io_manager = io_manager->GetWeakPtr() //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
const auto& task_runners = shell->GetTaskRunners();
// The animator is owned by the UI thread but it gets its vsync pulses
// from the platform.
auto animator = std::make_unique<Animator>(*shell, task_runners,
std::move(vsync_waiter));
engine = std::make_unique<Engine>(*shell, //
*shell->GetDartVM(), //
std::move(isolate_snapshot), //
std::move(shared_snapshot), //
task_runners, //
shell->GetSettings(), //
std::move(animator), //
std::move(snapshot_delegate), //
std::move(io_manager) //
);
ui_latch.Signal();
}));
ui_latch.Wait();
最后通过shell->Setup方法将platform_view engine rasterizer io_manager四个对象交给 Shell对象管理:
// We are already on the platform thread. So there is no platform latch to
// wait on.
if (!shell->Setup(std::move(platform_view), //
std::move(engine), //
std::move(rasterizer), //
std::move(io_manager)) //
) {
return nullptr;
}
return shell;
再回到前面的android_shell_holder.cc中,通过Shell::Create()创建完成后的shell对象返回给AndroidShellHolder对象持有。到这里整体思路就清晰了,Embedder层通过Shell对象与Engine层建立了连接,后续的一切操作通过Shell对象进行。而Shell对象又通过AndroidShellHolder对象持有,AndroidShellHolder对象指针值又返回给了java层,然后java层在调用JNI方法的时候将这个指针值传递过去便能拿到Embedder层的AndroidShellHolder对象,进而通过Shell对象向engine层发送一系列操作指令。
5.RunBundle
经过上面的流程,已经为dart层代码执行创建好了运行时环境,接下来就是加载dart层相关的代码了。
再回到java层的FlutterActivityDelegate中的onCreate代码:
//FlutterActivityDelegate.java/onCreate
if (!this.loadIntent(this.activity.getIntent())) {
String appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());
if (appBundlePath != null) {
this.runBundle(appBundlePath);
}
}
//FlutterActivityDelegate.java/runBundle
private void runBundle(String appBundlePath) {
if (!this.flutterView.getFlutterNativeView().isApplicationRunning()) {
FlutterRunArguments args = new FlutterRunArguments();
ArrayList<String> bundlePaths = new ArrayList();
ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater();
if (resourceUpdater != null) {
File patchFile = resourceUpdater.getInstalledPatch();
JSONObject manifest = resourceUpdater.readManifest(patchFile);
if (resourceUpdater.validateManifest(manifest)) {
bundlePaths.add(patchFile.getPath());
}
}
bundlePaths.add(appBundlePath);
args.bundlePaths = (String[])bundlePaths.toArray(new String[0]);
args.entrypoint = "main";
this.flutterView.runFromBundle(args);
}
}
调用自己的runBundle函数,在if语句里面可以看到资源提取的代码,这里是Flutter预埋的动态更新代码,目前应该还没起作用,然后会调用FlutterView runFromBundle:
// FlutterView.java
public void runFromBundle(FlutterRunArguments args) {
this.assertAttached();
this.preRun();
this.mNativeView.runFromBundle(args);
this.postRun();
}
java层最终会调到FlutterJNI中,其中nativePlatformViewId就是AndroidShellHolder在java层的指针值,此时的prioritizedBundlePaths数组中只有一个值类似/data/data/包名/flutter/flutter_assets/的路径值,entrypointFunctionName为main,pathToEntrypointFunction为null。
// FlutterJNI.java
@UiThread
public void runBundleAndSnapshotFromLibrary(
@NonNull String[] prioritizedBundlePaths,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager assetManager
) {
ensureAttachedToNative();
nativeRunBundleAndSnapshotFromLibrary(
nativePlatformViewId,
prioritizedBundlePaths,
entrypointFunctionName,
pathToEntrypointFunction,
assetManager
);
}
private native void nativeRunBundleAndSnapshotFromLibrary(
long nativePlatformViewId,
@NonNull String[] prioritizedBundlePaths,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager manager
);
后面就到了JNI层了,在PlatformViewAndrod中:
// platform_view_android_jni.cc
{
.name = "nativeRunBundleAndSnapshotFromLibrary",
.signature = "(J[Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Landroid/content/res/AssetManager;)V",
.fnPtr =
reinterpret_cast<void*>(&shell::RunBundleAndSnapshotFromLibrary),
},
// RunBundleAndSnapshotFromLibrary
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jobjectArray jbundlepaths,
jstring jEntrypoint,
jstring jLibraryUrl,
jobject jAssetManager) {
auto asset_manager = std::make_shared<blink::AssetManager>();
for (const auto& bundlepath :
fml::jni::StringArrayToVector(env, jbundlepaths)) {
if (bundlepath.empty()) {
continue;
}
// If we got a bundle path, attempt to use that as a directory asset
// bundle or a zip asset bundle.
const auto file_ext_index = bundlepath.rfind(".");
if (bundlepath.substr(file_ext_index) == ".zip") {
asset_manager->PushBack(std::make_unique<blink::ZipAssetStore>(
bundlepath, "assets/flutter_assets"));
} else {
asset_manager->PushBack(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
bundlepath.c_str(), false, fml::FilePermission::kRead)));
// Use the last path component of the bundle path to determine the
// directory in the APK assets.
const auto last_slash_index = bundlepath.rfind("/", bundlepath.size());
if (last_slash_index != std::string::npos) {
auto apk_asset_dir = bundlepath.substr(
last_slash_index + 1, bundlepath.size() - last_slash_index);
asset_manager->PushBack(std::make_unique<blink::APKAssetProvider>(
env, // jni environment
jAssetManager, // asset manager
std::move(apk_asset_dir)) // apk asset dir
);
}
}
}
上面逻辑首先通过bundlePath创建DirectoryAssetBundle对象交给asset_manager对象管理,然后欻功能键运行配置对象config,通过ANDROID_SHELL_HOLDER->Launch(std::move(config));根据运行配置信息启动,ANDROID_SHELL_HOLDER是一个宏,通过将java层持有的AndroidShellHolder指针值强转为AndroidShellHolder对象指针,这样就可以调用它的方法了。
// platform_view_android_jni.cc
#define ANDROID_SHELL_HOLDER \
(reinterpret_cast<shell::AndroidShellHolder*>(shell_holder))
再看到AndroidShellHolder中的方法Launch,就是到shell中取出engine,然后在UIThread中运行engine->Run:
void AndroidShellHolder::Launch(RunConfiguration config) {
if (!IsValid()) {
return;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
fml::MakeCopyable([engine = shell_->GetEngine(), //
config = std::move(config) //
]() mutable {
FML_LOG(INFO) << "Attempting to launch engine configuration...";
if (!engine || engine->Run(std::move(config)) ==
shell::Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch engine in configuration.";
} else {
FML_LOG(INFO) << "Isolate for engine configuration successfully "
"started and run.";
}
}));
}
再看下engine->Run:
// engine.cc
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
if (!configuration.IsValid()) {
FML_LOG(ERROR) << "Engine run configuration was invalid.";
return RunStatus::Failure;
}
auto isolate_launch_status =
PrepareAndLaunchIsolate(std::move(configuration));
...
return isolate_running ? Engine::RunStatus::Success
: Engine::RunStatus::Failure;
}
shell::Engine::RunStatus Engine::PrepareAndLaunchIsolate(
RunConfiguration configuration) {
...
if (configuration.GetEntrypointLibrary().empty()) {
if (!isolate->Run(configuration.GetEntrypoint())) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
} else {
if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(),
configuration.GetEntrypoint())) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
}
return RunStatus::Success;
}
最终调到DartIsolate的Run方法, 通过DartInvokeField执行到Dart层的main()方法入口,这样整个Dart代码就跑起来了,Flutter界面也就显示到FlutterView中。
// dart_isolate.cc
FML_WARN_UNUSED_RESULT
bool DartIsolate::Run(const std::string& entrypoint_name, fml::closure on_run) {
TRACE_EVENT0("flutter", "DartIsolate::Run");
if (phase_ != Phase::Ready) {
return false;
}
tonic::DartState::Scope scope(this);
auto user_entrypoint_function =
Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));
if (!InvokeMainEntrypoint(user_entrypoint_function)) {
return false;
}
phase_ = Phase::Running;
FML_DLOG(INFO) << "New isolate is in the running state.";
if (on_run) {
on_run();
}
return true;
}
FML_WARN_UNUSED_RESULT
static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function) {
if (tonic::LogIfError(user_entrypoint_function)) {
FML_LOG(ERROR) << "Could not resolve main entrypoint function.";
return false;
}
Dart_Handle start_main_isolate_function =
tonic::DartInvokeField(Dart_LookupLibrary(tonic::ToDart("dart:isolate")),
"_getStartMainIsolateFunction", {});
if (tonic::LogIfError(start_main_isolate_function)) {
FML_LOG(ERROR) << "Could not resolve main entrypoint trampoline.";
return false;
}
if (tonic::LogIfError(tonic::DartInvokeField(
Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMainZoned",
{start_main_isolate_function, user_entrypoint_function}))) {
FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
return false;
}
return true;
}
6.总结
整个代码比较长,简单总结就是在Android平台上Flutter是显示到FlutterView上的,FlutterView会通过FlutterNativeView调用到FlutterJNI,在FlutterJNI会持有一个很重要的对象AndroidShellHolder,而 AndroidShellHolder会持有shell对象, Embedder层通过Shell对象与Engine层建立了连接,后续的一切操作通过Shell对象进行。AndroidShellHolder对象指针值又返回给了java层,然后FlutterJNI在调用JNI方法的时候将这个指针值传递过去便能拿到Embedder层的AndroidShellHolder对象,进而通过Shell对象向engine层发送一系列操作指令。Engine对象会调用dart层代码执行。
参考链接: