深入分析 Flutter 初始化流程
在調(diào)研 Flutter 動(dòng)態(tài)化方案的時(shí)候,需要了解 Flutter 加載 dart 產(chǎn)物的流程,閱讀了一部分源碼,順便也讀了初始化相關(guān)的代碼。于是梳理了一遍 Flutter 的初始化流程
flutter的源碼下載地址在 github 上可以找到,具體地址: github-flutter/engine
FLutterMain的初始化
先從 Android 的入口開始看
在 FlutterAppliation 的 onCreate 中調(diào)用了
FlutterMain.startInitialization(this); 復(fù)制代碼跟進(jìn)去我們會(huì)看到調(diào)用了 startInitialization 方法,最后會(huì)順序調(diào)用這幾個(gè)方法
initConfig(applicationContext); initAot(applicationContext); initResources(applicationContext); 復(fù)制代碼我們查看 initResources 方法如圖
這里我們可以看到實(shí)際加載了assets里面的flutter資源。并且會(huì)把資源 copy 到本地的路徑。這里不做深究。FlutterMan 的初始化基本包括了
- 初始化配置
- 初始化 AOT 編譯
- 初始化資源
3 個(gè)部分
繼續(xù)看 Flutter 的 View 的初始化:
FLutterView的初始化
以 FlutterActivity 為例,在 onCreate 中會(huì)調(diào)用到 FlutterActivityDelegate 的對(duì)應(yīng)方法,最終調(diào)用 FlutterView 的 runFromBundle 方法
public void runFromBundle(FlutterRunArguments args) {this.assertAttached();this.preRun();this.mNativeView.runFromBundle(args);this.postRun(); } 復(fù)制代碼跟蹤這段代碼,會(huì)調(diào)用 FlutterNativeView 的 nativeRunBundleAndSnapshotFromLibrary方法。
這里會(huì)繼續(xù)進(jìn)行 jni 層的調(diào)用,查看 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), }, 復(fù)制代碼查看 RunBundleAndSnapshotFromLibrary,這里刪除了一些我們不關(guān)心的邏輯
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)) {const auto file_ext_index = bundlepath.rfind(".");if (bundlepath.substr(file_ext_index) == ".zip") {asset_manager->PushBack(std::make_unique<blink::ZipAssetStore>(bundlepath));} else {asset_manager->PushBack(std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(bundlepath.c_str(), false, fml::FilePermission::kRead)));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 environmentjAssetManager, // asset managerstd::move(apk_asset_dir)) // apk asset dir);}}} auto isolate_configuration = CreateIsolateConfiguration(*asset_manager); RunConfiguration config(std::move(isolate_configuration),std::move(asset_manager)); ANDROID_SHELL_HOLDER->Launch(std::move(config)); 復(fù)制代碼首先會(huì)對(duì)資源路徑進(jìn)行處理 會(huì)分為 zip包或者文件夾進(jìn)行分別處理。最終會(huì)調(diào)用常量ANDROID_SHELL_HOLDER 的 Launch 函數(shù).
最終走到 engine 的 Run 函數(shù)。
這里有 2 個(gè)函數(shù)比較重要,先是 IsolateConfiguration::PrepareIsolate, 然后是 RunFromLibrary 或者 Run 函數(shù)
跟到 PrepareAndLaunchIsolate 函數(shù),查看源碼
bool IsolateConfiguration::PrepareIsolate(blink::DartIsolate& isolate) {if (isolate.GetPhase() != blink::DartIsolate::Phase::LibrariesSetup) {FML_DLOG(ERROR)<< "Isolate was in incorrect phase to be prepared for running.";return false;}return DoPrepareIsolate(isolate); } 復(fù)制代碼而有 DoPrepareIsolate 函數(shù)的類 Configuration 類有3個(gè)
- AppSnapshotIsolateConfiguration
- KernelIsolateConfiguration
- KernelListIsolateConfiguration
他們分別會(huì)調(diào)用 DartIsolate 的
- PrepareForRunningFromPrecompiledCode
- PrepareForRunningFromKernel
這2個(gè)方法的一個(gè),可以看到這里的prepare操作分成了 預(yù)先加載的代碼 和 從內(nèi)核獲取 2種
至于 RunFromLibrary 函數(shù)和 Run 函數(shù)
我們能看到他們最終都會(huì)調(diào)用 dart:isolate 和 _startMainIsolate 的邏輯:
Dart_Handle isolate_lib = Dart_LookupLibrary(tonic::ToDart("dart:isolate")); if (tonic::LogIfError(Dart_Invoke(isolate_lib, tonic::ToDart("_startMainIsolate"),sizeof(isolate_args) / sizeof(isolate_args[0]), isolate_args))) {return false;} 復(fù)制代碼這里說(shuō)明我們正在執(zhí)行調(diào)用 Dart 的入口方法。而 Run 和 RunFromLibrary 的區(qū)別,則是如果我們傳入了 entrypoint 參數(shù)去進(jìn)行 Flutter 的 bundle 初始化的時(shí)候,則會(huì)去加載我們制定的 library。
小結(jié)
到這里, Flutter 的初始化流程就就簡(jiǎn)單的分析了一遍。大致可以總結(jié)成三個(gè)部分
初始化的邏輯比較復(fù)雜,對(duì)后續(xù)一些初始化相關(guān)的性能優(yōu)化應(yīng)該也會(huì)有不小的啟發(fā)。FlutterMain 中對(duì)資源的處理和寫入本地的邏輯也給 Android 端研究 Flutter 動(dòng)態(tài)化提供了基礎(chǔ)。
很多 bundle 加載和后續(xù)初始化的邏輯也還沒有完全弄清楚和深入研究。有興趣的朋友可以一起研究,共同探討。
總結(jié)
以上是生活随笔為你收集整理的深入分析 Flutter 初始化流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 几种排序算法
- 下一篇: Netty - 传输