Flutter 2,面试官问的那些 Android 原理你都懂吗
所以就像例子上所示,你可以在一个
Activity
上显示两个独立的 FlutterView 。
这其实得益于通过 FlutterEngineGroup
生成的 FlutterEngine
可以共享 GPU 上下文, font metrics 和 isolate group snapshot ,从而实现了更快的初始速度和更低的内存占用。
下图是使用官方实例打开 16 个页面之后的内存使用情况,并且每个页面成功返回且没有出现黑屏。
简单的使用介绍
使用 FlutterEngineGroup
首先需要创建一个 FlutterEngineGroup
单例对象,之后每当需要创建 Engine 时,就通过它的 createAndRunEngine(activity, dartEntrypoint)
来创建对应的 FlutterEngine
。
val app = activity.applicationContext as App// This has to be lazy to avoid creation before the FlutterEngineGroup.val dartEntrypoint =DartExecutor.DartEntrypoint(FlutterInjector.instance().flutterLoader().findAppBundlePath(), entrypoint)engine = app.engines.createAndRunEngine(activity, dartEntrypoint)this.delegate = delegatechannel = MethodChannel(engine.dartExecutor.binaryMessenger, "multiple-flutters")
以官方 Demo 的这段代码为例子:
1、首先通过 findAppBundlePath
和 entrypoint
创建出 DartEntrypoint
对象,这里的 findAppBundlePath
主要就是默认的 flutter_assets
目录;而 entrypoint
其实就是 dart 代码里启动方法的名称;也就是绑定了在 dart 中 runApp
的方法。
///kotlinapp.engines.createAndRunEngine(pathToBundle, "topMain")
///dart@pragma('vm:entry-point')void topMain() => runApp(MyApp());
2、通过上面创建的 dartEntrypoint
和 context
,使用 FlutterEngineGroup
就可以创建出对应的 FlutterEngine
,其实在内部就是通过FlutterJNI.nativeSpawn
和原有的引擎交互,得到新的 Long 地址 id。
在 C++ 层类似
于原有的 RunBundleAndSnapshotFromLibrary
方法,但是它不能更改包路径或者 asset ,所以只能加载同一份 AOT 文件,这里得到的指针地址就是一个新的 AndroidShellHolder
。
3、最后利用生成的 FlutterEngine
的 binaryMessenger
来得到一个 MethodChannel
用于原生和 dart 之间的通信。
通过上述流程得到的 Engine ,自然就可以直接用于渲染运行新的 Flutter UI,比如直接继承 FlutterActivity
,然后 override provideFlutterEngine
方法返回得到的 Engine 。
class SingleFlutterActivity : FlutterActivity()
·······
override fun provideFlutterEngine(context: Context): FlutterEngine? {return engine}
}
评论