在调研 Flutter 动态化方案的时候,需要了解 Flutter 加载 dart 产物的流程,阅读了一部分源码,顺便也读了初始化相关的代码。于是梳理了一遍 Flutter 的初始化流程

flutter的源码下载地址在 github 上可以找到,具体地址: github-flutter/engine

FLutterMain的初始化

先从 Android 的入口开始看

FlutterAppliationonCreate 中调用了

FlutterMain.startInitialization(this);
复制代码

跟进去我们会看到调用了 startInitialization 方法,最后会顺序调用这几个方法

initConfig(applicationContext);
initAot(applicationContext);
initResources(applicationContext);
复制代码

我们查看 initResources 方法如图

这里我们可以看到实际加载了assets里面的flutter资源。并且会把资源 copy 到本地的路径。这里不做深究。FlutterMan 的初始化基本包括了

  • 初始化配置
  • 初始化 AOT 编译
  • 初始化资源

3 个部分

继续看 FlutterView 的初始化:

FLutterView的初始化

FlutterActivity 为例,在 onCreate 中会调用到 FlutterActivityDelegate 的对应方法,最终调用 FlutterViewrunFromBundle 方法

public void runFromBundle(FlutterRunArguments args) {this.assertAttached();this.preRun();this.mNativeView.runFromBundle(args);this.postRun();
}
复制代码

跟踪这段代码,会调用 FlutterNativeViewnativeRunBundleAndSnapshotFromLibrary方法。

这里会继续进行 jni 层的调用,查看 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)) {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));
复制代码

首先会对资源路径进行处理 会分为 zip包或者文件夹进行分别处理。最终会调用常量ANDROID_SHELL_HOLDERLaunch 函数.

最终走到 engineRun 函数。

这里有 2 个函数比较重要,先是 IsolateConfiguration::PrepareIsolate, 然后是 RunFromLibrary 或者 Run 函数

跟到 PrepareAndLaunchIsolate 函数,查看源码

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);
}
复制代码

而有 DoPrepareIsolate 函数的类 Configuration 类有3个

  • AppSnapshotIsolateConfiguration
  • KernelIsolateConfiguration
  • KernelListIsolateConfiguration

他们分别会调用 DartIsolate

  • PrepareForRunningFromPrecompiledCode
  • PrepareForRunningFromKernel

这2个方法的一个,可以看到这里的prepare操作分成了 预先加载的代码从内核获取 2种

至于 RunFromLibrary 函数和 Run 函数

我们能看到他们最终都会调用 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;}
复制代码

这里说明我们正在执行调用 Dart 的入口方法。而 RunRunFromLibrary 的区别,则是如果我们传入了 entrypoint 参数去进行 Flutter 的 bundle 初始化的时候,则会去加载我们制定的 library。

小结

到这里, Flutter 的初始化流程就就简单的分析了一遍。大致可以总结成三个部分

  1. 初始化 FlutterMain
  2. 初始化 FlutterView,开始加载 bundle
  3. 初始化Flutter Bundle,这里获取了 Flutter 的入口方法、Flutter 的 library, 以及对 Flutter 入口方法的调用。

初始化的逻辑比较复杂,对后续一些初始化相关的性能优化应该也会有不小的启发。FlutterMain 中对资源的处理和写入本地的逻辑也给 Android 端研究 Flutter 动态化提供了基础。

很多 bundle 加载和后续初始化的逻辑也还没有完全弄清楚和深入研究。有兴趣的朋友可以一起研究,共同探讨。

深入分析 Flutter 初始化流程相关推荐

  1. 关于Flutter初始化流程,我必须告诉你的是...

    作者:闲鱼技术-然道 1. 引言 最近在做性能优化的时候发现,在混合栈开发中,第一次启动Flutter页面的耗时总会是第二次启动Flutter页面耗时的两倍左右,这样给人感觉很不好.分析发现第一次启动 ...

  2. Linux内核网络栈1.2.13-网卡设备的初始化流程

    参考资料 <<linux内核网络栈源代码情景分析>> 网卡设备的初始化 本文主要描述一下网卡设备的整个初始化的过程,该过程主要就是根据设备的硬件信息来获取与传输网络数据,注册相 ...

  3. 开机流程简介--init 处理系统初始化流程 (/etc/rc.d/rc.sysinit)

    init 处理系统初始化流程 (/etc/rc.d/rc.sysinit) 还记得上面提到 /etc/inittab 里头有这一句' si::sysinit:/etc/rc.d/rc.sysinit ...

  4. SpringMVC源码剖析(三)- DispatcherServlet的初始化流程

    我们启动web服务器,在浏览器中输入地址,就可以看到浏览器上输出我们写好的页面.为了更好的理解上面这个过程,你需要学习关于Servlet生命周期的三个阶段,就是所谓的"init-servic ...

  5. android6.0源码分析之Camera API2.0下的初始化流程分析

    1.Camera2初始化的应用层流程分析 Camera2的初始化流程与Camera1.0有所区别,本文将就Camera2的内置应用来分析Camera2.0的初始化过程.Camera2.0首先启动的是C ...

  6. caffe模型文件解析_深度学习 Caffe 初始化流程理解(数据流建立)

    深度学习 Caffe 初始化流程理解(数据流建立) 之前在简书的文章,搬迁过来 ^-^ 本文是作者原创,如有理解错误,恳请大家指出,如需引用,请注明出处. #Caffe FeatureMap数据流的建 ...

  7. linux内核ufs设备树,Linux内核初始化流程笔记

    Linux内核初始化流程笔记 分类: LINUX 作者:gfree.wind@http://www.doczj.com/doc/fc580419c1c708a1294a4409.html 博客:htt ...

  8. Ethercat解析(十四)之初始化流程

    一.EtherCAT入口 源代码执行命令sudo /etc/init.d/ethercat start,将会从文件module.c文件中的ec_init_module函数中开始往下执行初始化流程. 二 ...

  9. ssd1306 OLED 初始化流程

    参考博客:SSD1306驱动理解_夏沫的杂物间-CSDN博客_ssd1306驱动 IIC学习:  I2C 协议分析和学习_Car12-CSDN博客 SSD1306 IIC读写时序 1. 第一个字节(S ...

最新文章

  1. Socket接收器——Acceptor
  2. 我也谈javascript闭包
  3. java如何画百分比圆环_canvas绘制百分比圆环进度条
  4. ceph iscsi安装
  5. [原创软件]手机截屏及格式转换工具
  6. Coolite Toolkit学习笔记七:常用控件TreePanel
  7. dqkg的命令用法_CADk中常用命令使用方法及说明
  8. 天思经理人ERP塑胶玩具行业应用方案
  9. 浏览器 cookie 和 session 的认识
  10. PyTorch 实现kmax-pooling
  11. matlab 带通滤波,MATLAB窗函数实现带通滤波器
  12. QQ空间说说批量删除
  13. 解决XP系统桌面图标蓝底
  14. SRVCC关键场景及Log分析
  15. 电容式计算机键盘的按键下,计算机键盘开关
  16. 小程序直接跳转公众号的必要条件记录
  17. 钉钉邮箱登录入口_清博舆情钉钉小程序上线 ,五大优势三大亮点助力工作更高效...
  18. 什么是UEFI启动?
  19. 高等数学基础概念的Python开发实现
  20. Hadoop性能调优全面总结

热门文章

  1. python网页运行环境_Python小牛叔Web开发1:安装Visual Studio Code配置Python运行环境...
  2. jsp 连接mysql空指针_java jdbc与mysql为什么连接不上并且抛出空指针异常?
  3. 多头注意力机制的理解
  4. android tablayout 字体颜色,Tablayout变颜色 以及Fragment进行切换
  5. 条形图坐标轴_手把手教你用Excel绘图 | 双轴簇状条形图
  6. 复杂update_Python 代码判断逻辑太复杂?这里有几条最佳实践和技巧
  7. js和css被屏蔽了,拦截器 Filter ,js、css、image等静态资源不被拦截解决方案
  8. Linux IO路径图
  9. 【项目管理】采购管理
  10. 《系统集成项目管理工程师》必背100个知识点-56X理论和Y理论