延迟组件主要通过 dart 中的 loadLibrary()
调用来触发被下载、安装和加载。这个调用在 dart2js 和 aot/native 中的处理是不同的。这里,我们梳理 loadLibrary()
调用转换为一个延迟组件的安装过程:
dart 中 loadLibrary()
会调用的 native 层的 Dart_DeferredLoadHandler 函数,该回调函数在DartIsolate::Initialize 中由 Dart_SetDeferredLoadHandler 设置。Dart 在内部检索分配给库的加载单元 ID,并将其传递给回调函数。回调到 DartIsolate::OnDartLoadLibrary。
加载单元 ID 然后通过 runtime controller、engine 和 platform view 传递到 Android 嵌入层中的 FlutterJNI。这里,加载单元 ID 被传递到 DeferredComponentsManager
的 installDeferredComponent
方法中, ID 从一个整数映射为一个 String 名称,标识请求库所属的 pubspec 定义的延迟组件。这个转换由 AndroidManifest 中的 meta-data 映射,在构建阶段创建并验证。
之后 PlayStoreDeferredComponentManager
调用 API 下载 module。module 安装会定位到 .so
文件,并将路径传递给 engine 执行 dloopen
。engine 将解析的符号发送到 dart isolate,以此将这些符号加载到 dart VM 中。整个加载过程必须与加载单元 ID 关联,否则 loadLibrary()
返回的 Future
对象不会完成。
请记住,多个加载单元可能包含在一个延迟组件中,但是 loadLibrary
只会从调用的特定 dart 库中加载 dart 符号。每个加载单元在使用前必须单独的调用 loadLibrary
。对已经下载过的组件,后续调用 loadLibrary
不会二次加载,但是也并非同步完成,在调用和完成之间至少有一帧间隔。
通过延迟组件名称进行安装
我们还提供了 <