Flutter启动流程源码分析
Flutter的启动从java代码层面上看是离不开FlutterApplication、FlutterActivity这两个类的,下面我们就以flutter1.12.13版本为例来看下源码
一、FlutterApplication启动流程
1.1、FlutterApplication.onCreate
public void onCreate() {
super.onCreate();
// 初始化flutter相关资源
FlutterMain.startInitialization(this);
}
1.2、FlutterMain
Flutter engine初始化类
public static void startInitialization(@NonNull Context applicationContext) {
if (isRunningInRobolectricTest) {
return;
}
// 从1.9.1+hotfix.6时单独抽出了一个单例FlutterLoader
FlutterLoader.getInstance().startInitialization(applicationContext);
}
1.3、FlutterLoader
在apk中查找flutter resources并加载libflutter.so
FlutterLoader-->startInitialization
public void startInitialization(@NonNull Context applicationContext) {
// 初始化一个默认的Setting
startInitialization(applicationContext, new Settings());
}
public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
// 首次执行时全局的settings还未被赋值,保证startInitialization只执行一次
if (this.settings != null) {
return;
}
// 保证在主线程中执行初始化操作
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
}
// 使用application的context.
applicationContext = applicationContext.getApplicationContext();
// 给全局的settings赋值
this.settings = settings;
long initStartTimestampMillis = SystemClock.uptimeMillis();
// 初始化配置
initConfig(applicationContext);
// 初始化资源加载
initResources(applicationContext);
// 这个类的主要作用之一:加载libflutter.so
System.loadLibrary("flutter");
VsyncWaiter.getInstance(
(WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE))
.init();
long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
// 调用C层代码记录一下application启动的时间
FlutterJNI.nativeRecordStartTimestamp(initTimeMillis);
}
FlutterLoader-->initConfig
加载androidManifest.xml中的flutter相关的配置:
1、aot模式时libapp.so库的位置(默认在lib/armeabi-v7a或者lib/arm64-v8a文件夹下)
2、flutter_assets资源文件的路径(默认在assets文件夹下)
3、JIT模式时vm_snapshot_data的位置(默认在debug时在flutter_assets文件夹下)
4、JIT模式时isolate_snapshot_data的位置(默认在debug时在flutter_assets文件夹下)
private void initConfig(@NonNull Context applicationContext) {
Bundle metadata = getApplicationInfo(applicationContext).metaData;
// There isn't a `<meta-data>` tag as a direct child of `<application>` in
// `AndroidManifest.xml`.
if (metadata == null) {
return;
}
aotSharedLibraryName =
metadata.getString(PUBLIC_AOT_SHARED_LIBRARY_NAME, DEFAULT_AOT_SHARED_LIBRARY_NAME);
flutterAssetsDir =
metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, DEFAULT_FLUTTER_ASSETS_DIR);
vmSnapshotData = metadata.getString(PUBLIC_VM_SNAPSHOT_DATA_KEY, DEFAULT_VM_SNAPSHOT_DATA);
isolateSnapshotData =
metadata.getString(PUBLIC_ISOLATE_SNAPSHOT_DATA_KEY, DEFAULT_ISOLATE_SNAPSHOT_DATA);
}
FlutterLoader.initResources
在debug或者JIT模式下,加载vm_snapshot_data、isolate_snapshot_data、kernel_blob.bin
private void initResources(@NonNull Context applicationContext) {
// 先清空data/user/0/package/cache目录下文件
new ResourceCleaner(applicationContext).start();
// debug或者JIT模式
if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
// data/user/0/package/app_flutter目录
final String dataDirPath = PathUtils.getDataDirectory(applicationContext);
final String packageName = applicationContext.getPackageName();
final PackageManager packageManager = applicationContext.getPackageManager();
final AssetManager assetManager = applicationContext.getResources().getAssets();
resourceExtractor =
new ResourceExtractor(dataDirPath, packageName, packageManager, assetManager);
// 资源加载到列表中
resourceExtractor
.addResource(fullAssetPathFrom(vmSnapshotData)) // fullAssetPathFrom是拼写flutter_assets全路径的方法
.addResource(fullAssetPathFrom(isolateSnapshotData))
.addResource(fullAssetPathFrom(DEFAULT_KERNEL_BLOB));
// 启动一个AsyncTask任务,会将data/user/0/package/app_flutter目录下对应的vm_snapshot_data、isolate_snapshot_data、kernel_blob.bin的文件先删除,然后从apk安装目录的assets中复制新的文件使用
resourceExtractor.start();
}
}
1.4、FlutterJNI
调用libflutter.so时用到的JNI方法封装
// 记录application启动的时间
public static native void nativeRecordStartTimestamp(long initTimeMillis);
1.5、flutter_main.cc
主要是定义了两个方法:nativeInit、nativeRecordStartTimestamp
bool FlutterMain::Register(JNIEnv* env) {
static const JNINativeMethod methods[] = {
// 。。。。。。省略其他代码
{
// JNI方法nativeRecordStartTimestamp,转化成调用C++的RecordStartTimestamp方法
.name = "nativeRecordStartTimestamp",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&RecordStartTimestamp),
},
};
// 。。。。。。省略其他代码
}
1.6、libary_loader.cc
在加载libflutter.so时会触发JNI_OnLoad方法
// 注册FlutterMain的JNI方法
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// 。。。。。。省略其他代码
result = flutter::FlutterMain::Register(env);
// 。。。。。。省略其他代码
}
附FlutterApplication时序图
image-flutter-application.png
二、FlutterActivity
在flutter中有两个FlutterActivity,一个是io.flutter.app.FlutterActivity,另一个是io.flutter.embedding.android.FlutterActivity,前者是老版本的Flutter运行相关类,在1.12版本已经不建议使用了。参考文档https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects,下面讲解的都是io.flutter.embedding.android.FlutterActivity。
2.1、FlutterActivity
2.1.1、onCreate
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 查看metedata中是否有配置主题
switchLaunchThemeForNormalTheme();
super.onCreate(savedInstanceState);
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
// 初始化delegate
delegate = new FlutterActivityAndFragmentDelegate(this);
// 初始化flutter engine相关
delegate.onAttach(this);
// 为插件提供恢复状态的onRestoreInstanceState
delegate.onActivityCreated(savedInstanceState);
// 当Intent配置的backgroundMode是透明时,就配置window是否透明
configureWindowForTransparency();
// 创建FlutterView
setContentView(createFlutterView());
configureStatusBarForFullscreenFlutterExperience();
}
2.1.2、configureWindowForTransparency
public FlutterView.RenderMode getRenderMode() {
// 获取intent里传递的backgroundMode,opaque表示不透明
return getBackgroundMode() == BackgroundMode.opaque
? FlutterView.RenderMode.surface
: FlutterView.RenderMode.texture;
}
private void configureWindowForTransparency() {
BackgroundMode backgroundMode = getBackgroundMode();
if (backgroundMode == BackgroundMode.transparent) {
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
);
}
}
2.1.3、createFlutterView
private View createFlutterView() {
// 通过代理创建flutterView
return delegate.onCreateView(
null /* inflater */,
null /* container */,
null /* savedInstanceState */);
}
2.2、FlutterActivityAndFragmentDelegate
2.2.1、onAttach
主要做以下几件事:
1、获取或者创建flutter engine
2、创建和配置PlatformPlugin
3、将flutterEngine附加到activity
void onAttach(@NonNull Context context) {
ensureAlive();
// 当这个FlutterActivity是复用时,flutter engine复用
if (flutterEngine == null) {
setupFlutterEngine();
}
// 创建和配置platform plugin
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);
if (host.shouldAttachEngineToActivity()) {
// 将flutter engine附加到activity
Log.d(TAG, "Attaching FlutterEngine to the Activity that owns this Fragment.");
flutterEngine.getActivityControlSurface().attachToActivity(
host.getActivity(),
host.getLifecycle()
);
}
// flutter activity配置flutter engine提供入口
host.configureFlutterEngine(flutterEngine);
}
2.2.2、onCreateView
View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.v(TAG, "Creating FlutterView.");
ensureAlive();
// 创建flutterView
flutterView = new FlutterView(host.getActivity(), host.getRenderMode(), host.getTransparencyMode());
flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);
// 创建一个在view直到flutter的第一帧显示出来
flutterSplashView = new FlutterSplashView(host.getContext());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
flutterSplashView.setId(View.generateViewId());
} else {
flutterSplashView.setId(486947586);
}
// 当flutter view第一帧渲染后会移除splash view
flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen());
return flutterSplashView;
}
三、FlutterEngine
3.1、构造方法时调用
public FlutterEngine(
@NonNull Context context,
@NonNull FlutterLoader flutterLoader,
@NonNull FlutterJNI flutterJNI,
@NonNull PlatformViewsController platformViewsController,
@Nullable String[] dartVmArgs,// FlutterActivity重写getFlutterShellArgs方法可以添加参数
boolean automaticallyRegisterPlugins) {
this.flutterJNI = flutterJNI;
// 初始化配置、资源、加载libflutter.so;如果使用了FlutterApplication,也不会重复初始化操作
flutterLoader.startInitialization(context.getApplicationContext());
// 确保初始化完成
flutterLoader.ensureInitializationComplete(context, dartVmArgs);
flutterJNI.addEngineLifecycleListener(engineLifecycleListener);
// 调用flutterJNI的attachToNative初始化setting配置
attachToJni();
this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
this.dartExecutor.onAttachedToJNI();
// 。。。。。省略
}
3.2、attachToJni
private void attachToJni() {
Log.v(TAG, "Attaching to JNI.");
// 通过FlutterJNI调用libflutter.so中的方法
flutterJNI.attachToNative(false);
if (!isAttachedToJni()) {
throw new RuntimeException("FlutterEngine failed to attach to its native Object reference.");
}
}
四、FlutterJNI
通过这个类调用flutter engine中的 C/C++ 代码,对应platform_view_android_jni.cc代码
// 将java层初始化的参数传递给C++层
public static native void nativeInit(
@NonNull Context context,
@NonNull String[] args,
@Nullable String bundlePath,
@NonNull String appStoragePath,
@NonNull String engineCachesPath);
// 初始化AndroidShellHolder
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
附上FlutterActivity启动时序图
了解完Flutter的启动流程,下一篇文章我们就来配置一下flutter engine的编译环境,以及一步步的实现flutter的动态化,敬请期待