引擎初始化与启动
本文也发布于本人的知乎专栏:https://zhuanlan.zhihu.com/p/394560540
0. 前言
Flutter是当前比较火热的前端开发框架,正好我最近也在做和Flutter引擎相关的工作,就顺手研究一下Flutter的源码。
源码主要分为两部分:
- Engine,是可供Flutter宿主应用提供的一个可移植运行时。Engine实现了Flutter的核心库,包括动画、图形、文件、网络I/O、访问支持、插件架构和Dart的运行时、编译工具链;
- Flutter Framework,大部分的Flutter开发者主要通过Flutter Framework交互。Framework提供了一个现代的、可交互的框架,以及一个丰富的平台、布局、基础部件的集合。
Flutter官方源码下载路径:
engine: https://github.com/flutter/engine
flutter framework: https://github.com/flutter/flutter
本文主要分析引擎的初始化流程和启动流程。
1. 初始化流程
1.1 Android平台适配层
众所周知,Android应用的入口基本都是Activity,那么我们就先从Flutter的Activity开始着手分析。
1.1.1 FlutterActivity
在Engine中存在两个FlutterActivity(shell/platform/android/io/flutter/app/FlutterActivity.java和shell/platform/android/io/flutter/embedding/android/FlutterActivity.java),其中在2020年5月13日的代码提交中,前一个FlutterActivity注释修改为废弃Activity基类。所以现在可用的Activity基类是后一个。
根据FlutterActivity的注释,我们可知:
FlutterActivity
是将Flutter集成到Android应用中的最简单最直接的方式,用于显示一个全屏的Flutter UI。主要职责是:
- 显示一个Android的lauch screen;
- 显示Flutter的splash screen;
- 设置状态栏;
- 选择Dart执行应用包路径和入口点;
- 选择Flutter的初始化路由;
- 如果需要的话,渲染透明度;
- 提供子类钩子,提供和配置FlutterEngine。
先从FlutterActivity
定义看起:
public class FlutterActivity extends Activity
implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner
FlutterActivity
继承于Activity
。FlutterActivityAndFragmentDelegate.Host
接口是在FlutterActivityAndFragmentDelegate
中FlutterActivity
持有类。
Activity
的onCreate
方法是入口关键方法,看一下FlutterActivity
的onCreate
方法:
// ./shell/platform/android/io/flutter/embedding/android/FlutterActivity.java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
switchLaunchThemeForNormalTheme(); // 设置主题
super.onCreate(savedInstanceState);
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); // 设置Android生命周期
delegate = new FlutterActivityAndFragmentDelegate(this); // [1]
delegate.onAttach(this);
delegate.onActivityCreated(savedInstanceState);
configureWindowForTransparency(); // 设置背景透明模式
setContentView(createFlutterView()); // [2]
configureStatusBarForFullscreenFlutterExperience(); // 配置系统状态栏
}
- [1]
FlutterActivityAndFragmentDelegate
类实现了FlutterActivity
与FlutterFragment
之间相同的逻辑。 - [2] 通过调用
FlutterActivityAndFragmentDelegate
的onCreateView
方法创建出FlutterView
并将其添加到界面上。FlutterView
用于在Android设备上显示Flutter UI。
1.1.2 FlutterActivityAndFragmentDelegate
下面就再分析一下FlutterActivityAndFragmentDelegate
的源码逻辑:
// ./shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java
final class FlutterActivityAndFragmentDelegate {
...
FlutterActivityAndFragmentDelegate(@NonNull Host host) {
this.host = host; // 保存FlutterActivity对象
}
...
// [3]
void onAttach(@NonNull Context context) {
...
setupFlutterEngine(); // 创建FlutterEngine
...
}
...
// [4]
@NonNull
View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
...
// 创建FlutterSurfaceView,用于提供绘制Flutter UI的Surface
FlutterSurfaceView flutterSurfaceView =
new FlutterSurfaceView(
host.getActivity(), host.getTransparencyMode() == TransparencyMode.transparent);
...
flutterView = new FlutterView(host.getActivity(), flutterSurfaceView);
...
flutterSplashView = new FlutterSplashView(host.getContext());
...
flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen());
flutterView.attachToFlutterEngine(flutterEngine);
return
}
...
return flutterSplashView;
}
- [3]
onAttach
方法主要做了以下事情:1. 初始化Flutter系统;2. 获取或者创建一个FlutterEngine
;3. 创建和配置PlatformPlugin
;4. 将FlutterEngine
附在Activity
上;5. 通过Host
的configureFlutterEngine
方法配置FlutterEngine
。 - [4] 'onCreateView’方法主要做以下事情:1. 在View树中创建一个新的
FlutterView
;2. 在FlutterView
中添加一个FlutterUiDisplayListener
;3. 将FlutterEngine
附着到FlutterView
上;4. 返回这个新的View树。
在这里出现了两个比较重要的类,FlutterView
和FlutterEngine
。
1.1.3 FlutterView
FlutterView
的作用是将Flutter UI通过对应的FlutterEngine
绘制后,显示在Android设备上。这里有两种渲染模式:surface
和texture
。
在一般情况,我们都使用surface
模式,即将Flutter UI绘制在SurfaceView
上,这种模式拥有最优的性能,缺点是无法置于两个其他Android View
的z-index之间,同时也无法动画化或者进行变换。
下面我们看一下FlutterView
的源码实现:
// ./shell/platform/android/io/flutter/embedding/android/FlutterView.java
public class FlutterView extends FrameLayout {
...
private FlutterView(
@NonNull Context context,
@Nullable AttributeSet attrs,
@NonNull FlutterSurfaceView flutterSurfaceView) {
super(context, attrs);
this.flutterSurfaceView = flutterSurfaceView;
this.renderSurface = flutterSurfaceView;
init();
}
...
private void init() {
...
addView(flutterSurfaceView);
...
// FlutterView needs to be focusable so that the InputMethodManager can interact with it.
setFocusable(true);
setFocusableInTouchMode(true);
}
...
// 将当前FlutterView连接到给定的FLutterEngine
// FlutterView将通过给定的FlutterEngine绘制UI,同时也将开始将后续的交互时间传递到FlutterEngine,
// 例如触摸事件、键盘事件等。
public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
...
this.flutterEngine = flutterEngine;
// Instruct our FlutterRenderer that we are now its designated RenderSurface.
FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer();
...
renderSurface.attachToRenderer(flutterRenderer); // [5]
...
// Initialize various components that know how to process Android View I/O
// in a way that Flutter understands.
...
// Push View and Context related information from Android to Flutter.
sendUserSettingsToFlutter();
sendLocalesToFlutter(getResources().getConfiguration());
sendViewportMetricsToFlutter();
flutterEngine.getPlatformViewsController().attachToView(this); // PlatformViewsController获取当前FlutterView
...
}
}
- [5] 将
FlutterSurfaceView
的Surface
提供给指定的FlutterRender
,用于将Flutter UI绘制到当前的FlutterSurfaceView
。
1.1.4 FlutterEngine
FlutterEngine
是一个独立的Flutter运行环境,是Dart代码运行在Android应用的容器。
// ./shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
/** Fully configurable {@code FlutterEngine} constructor. */
public FlutterEngine(
@NonNull Context context,
@NonNull FlutterLoader flutterLoader,
@NonNull FlutterJNI flutterJNI,
@NonNull PlatformViewsController platformViewsController,
@Nullable String[] dartVmArgs,
boolean automaticallyRegisterPlugins) {
this.flutterJNI = flutterJNI;
flutterLoader.startInitialization(context.getApplicationContext());
...
attachToJni();
this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
this.dartExecutor.onAttachedToJNI();
this.renderer = new FlutterRenderer(flutterJNI);
...
xxxChannel = new XxxChannel(