Flutter 引擎启动流程
基本流程
起于 Android 中,分别在 FlutterApplication 和 FlutterActivity 中执行了一部分的操作,并通过 JNI 进入 C++ 层,创建一系列 Flutter 的基础结构,Engine、Animator、Shell 等,通过 C++ 层完成 Java 和 Dart 通信,Java 中提供了许多基础功能的接口给 JNI ,Dart 可以通过 C++ 调用到,比如请求下一帧,或者是用于构建 Flutter Plugin 的 MethodCall 等功能。 完成 C++ 层的初始化之后,就会调用 Dart 的 main() 函数,进行 Flutter 应用的初始化,构建完了 Flutter 的运营体系之后,Flutter 就会通过调用 C++ 相关方法请求帧,并在帧的回调中完成一些绘制、动画工作,C++ 转而通过 JNI 调用 Android 中的 Choreographer 进行帧请求,得到 Callback 之后调用 Dart 中的相关方法。Flutter 得到 Callback 之后便执行一帧的绘制,会先处理一下动画数据,然后请求绘制,绘制过程中,先清理 Element Tree 中的脏节点,将其更新,再调用 C++ 完成画面绘制。
详细流程
FlutterApplication.onCreate()
调用 FlutterMain.startInitialization()。
FlutterMain.startInitialization()
- initConfig(Context):初始化配置
- initResource(Context):初始化资源文件
- System.loadLibrary(String):加载 JNI
- VsyncWaiter.init():初始化帧发生器
- FlutterJNI.nativeRecordStartTimestamp(long):记录时间
FlutterMain.initConfig(Context)
private static 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;
}
sAotSharedLibraryName = metadata.getString(PUBLIC_AOT_SHARED_LIBRARY_NAME, DEFAULT_AOT_SHARED_LIBRARY_NAME);
sFlutterAssetsDir = metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, DEFAULT_FLUTTER_ASSETS_DIR);
sVmSnapshotData = metadata.getString(PUBLIC_VM_SNAPSHOT_DATA_KEY, DEFAULT_VM_SNAPSHOT_DATA);
sIsolateSnapshotData = metadata.getString(PUBLIC_ISOLATE_SNAPSHOT_DATA_KEY, DEFAULT_ISOLATE_SNAPSHOT_DATA);
}
初始化配置,从 xml 文件中加载出 AotSharedLibraryName 等参数。
FlutterMain.initResource(Context)
private static void initResources(@NonNull Context applicationContext) {
new io.flutter.view.ResourceCleaner(applicationContext).start();
if (io.flutter.app.BuildConfig.DEBUG) {
final String dataDirPath = PathUtils.getDataDirectory(applicationContext);
final String packageName = applicationContext.getPackageName();
final PackageManager packageManager = applicationContext.getPackageManager();
final AssetManager assetManager = applicationContext.getResources().getAssets();
sResourceExtractor = new io.flutter.view.ResourceExtractor(dataDirPath, packageName, packageManager, assetManager);
// In debug/JIT mode these assets will be written to disk and then
// mapped into memory so they can be provided to the Dart VM.
sResourceExtractor
.addResource(fromFlutterAssets(sVmSnapshotData))
.addResource(fromFlutterAssets(sIsolateSnapshotData))
.addResource(fromFlutterAssets(DEFAULT_KERNEL_BLOB));
sResourceExtractor.start();
}
}
初始化资源文件,主要包括两个步骤,分别是删除缓存文件和加载 APK 资源。
ResourceCleaner
void start() {
File cacheDir = mContext.getCacheDir();
if (cacheDir == null) {
return;
}
final CleanTask task = new CleanTask(cacheDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
boolean result = name.startsWith(io.flutter.view.ResourcePaths.TEMPORARY_RESOURCE_PREFIX);
return result;
}
}));
if (!task.hasFilesToDelete()) {
return;
}
new Handler().postDelayed(new Runnable() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void run() {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}, DELAY_MS);
}
用于删除所有缓存文件。
ResourceExtractor
ResourceExtractor start() {
if (BuildConfig.DEBUG && mExtractTask != null) {
Log.e(TAG, "Attempted to start resource extraction while another extraction was in progress.");
}
mExtractTask = new ExtractTask(mDataDirPath, mResources, mPackageName, mPackageManager, mAssetManager);
mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return this;
}
protected Void doInBackground(Void... unused) {
final File dataDir = new File(mDataDirPath);
final String timestamp = checkTimestamp(dataDir, mPackageManager, mPackageName);
if (timestamp == null) {
return null;
}
deleteFiles(mDataDirPath, mResources);
if (!extractAPK(dataDir)) {
return null;
}
if (timestamp != null) {
try {
new File(dataDir, timestamp).createNewFile();
} catch (IOException e) {
Log.w(TAG, "Failed to write resource timestamp");
}
}
return null;
}
删除 APK 的资源文件并重新从 assets 文件夹中提取出新的资源文件。
System.loadLibrary(String)
加载 JNI 函数的方法,经过一系列调用会调用到 JNI_onLoad 函数,在此函数中先后调用了一下四个函数。
- fml::jni::AttachCurrentThread()
- flutter::FlutterMain::Register(env)
- flutter::PlatformViewAndroid::Register(env)
- flutter::VsyncWaiterAndroid::Register(env)
第一个函数将当前线程与 jvm 联系起来。
剩余三个函数,都是 Register 函数,分别用于 FlutterMain、PlatformViewAndroid 和 VsyncWaiterAndroid 的初始化,在 Register 函数中会建立 JNI 与 Java 之间的联系,方便之后 Java 调用 C++ 方法、通过 C++ 调用 Java 的方法或获取 Java 中某一个变量的值。
比如 VsyncWaiterAndroid 的 Register 函数:
bool VsyncWaiterAndroid::Register(JNIEnv* env) {
static const JNINativeMethod methods[] = {{
.name = "nativeOnVsync",
.signature = "(JJJ)V",
.fnPtr = reinterpret_cast<void*>(&OnNativeVsync),
}};
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
if (clazz == nullptr) {
return false;
}
g_vsync_waiter_class = new fml::jni::ScopedJavaGlobalRef<jclass>(env, clazz);
FML_CHECK(!g_vsync_waiter_class->is_null());
g_async_wait_for_vsync_method_ = env->GetStaticMethodID(
g_vsync_waiter_class->obj(), "asyncWaitForVsync", "(J)V");
FML_CHECK(g_async_wait_for_vsync_method_ != nullptr);
return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
}
VsyncWaiter.init()
先获取 VsyncWaiter 的实例,然后调用其 init 方法,
private final FlutterJNI.AsyncWaitForVsyncDelegate asyncWaitForVsyncDelegate = new FlutterJNI.AsyncWaitForVsyncDelegate() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void asyncWaitForVsync(long cookie) {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
float fps = windowManager.getDefaultDisplay().getRefreshRate();
long refreshPeriodNanos = (long) (1000000000.0 / fps);
FlutterJNI.nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
}
});
}
};
public void init() {
FlutterJNI.setAsyncWaitForVsyncDelegate(asyncWaitForVsyncDelegate);
float fps = windowManager.getDefaultDisplay().getRefreshRate();
FlutterJNI.setRefreshRateFPS(fps);
}
主要就是将 asyncWaitForVsyncDelegate 实例传递给 FlutterJNI ,FlutterJNI 从名字便可以看出这是一个用于与 C++ 通信的类,这一步的目的,就是将 Choreographer 作为帧的生成工具传递进去,当 Flutter 需要请求下一帧的时候,会通过 FlutterJNI 调用到 asyncWaitForVsync 方法,这个方法会调用 Choreographer.postFrameCallback ,当下一帧到来时,这个 callback 就会被调用,继而通过 FlutterJNI.nativeOnVsync 进行下一帧的处理工作。
FlutterJNI.nativeRecordStartTimestamp(long)
记录初始化的时间。
FlutterApplication 的初始化到此结束,从以上 startInitialization 所做的工作来看,它主要是就整个应用的基础设施层面,进行了资源、配置初始化,或是基础工具的初始化,也就是帧生成工具。
FlutterActivity
要在 Android 中使用 Flutter ,还需要使用一个继承自 FlutterActivity 的 Activity ,所以 FlutterActivity 中应该完成了 Flutter 整个功能结构的初始化工作,从实际跑起来的 demo 来看,启动 Flutter 应用之后总会有一段不短时间的黑屏过程,这个过程就是在执行 FlutterActivity 的启动准备工作。
FlutterActivity 实现了三个接口,分别是 FlutterView.Provider、PluginRegistry 和 ViewFactory 。
FlutterView.Provider
这个接口只有一个方法,
FlutterView getFlutterView();
提供一个 FlutterView 实例。
PluginRegistry
拥有三个抽象方法,
Registrar registrarFor(String pluginKey);
boolean hasPlugin(String pluginKey);
<T> T valuePublishedByPlugin(String pluginKey);
用于插件相关的功能,最主要的是 registrarFor ,这个方法会返回一个 Registrar 实例,Registrar 是自定义的插件能够直接获取到的数据,插件一般根据这个参数进行初始化。比如 shared_preference 插件的 registerWith 方法:
public static void registerWith(PluginRegistry.Registrar registrar) {
MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME);
SharedPreferencesPlugin instance = new SharedPreferencesPlugin(registrar.context());
channel.setMethodCallHandler(instance);
}
先创建了一个用于平台间通信的 MethodChannel 实例,然后 SharedPreferencePlugin 实例,并将实例传递给 MethodChannel ,SharedPreferencePlugin 实现了 MethodCallHandler 接口,提供了处理来自 Flutter 功能请求的方法 onMethodCall(MethodCall call, MethodChannel.Result result) ,可以解析 Flutter 的请求,并执行对应的功能,这就是一个插件的基本工作流程。
ViewFactory
提供了生成 FlutterView 和 FlutterNativeView 的方法,在 FlutterActivity 的 onCreate 方法中会先调用这两个方法获取 view ,如果返回 null(默认返回的是 null),则会创建对应的 view 。
这个步骤的作用应该是,用户可以在自己的 FlutterActivity 中实现这个方法,使用自己创建的 FlutterView 或 FlutterNativeView ,从而 hook 它们的某些方法,实现一些特殊的功能。
FlutterActivity 中除了 override 以上三个接口的方法外,还有关于生命周期的方法和一些事件类的方法,如 onLowMemor 、onConfigurationChanged 、onActivityResult 等。
而更多的事件,则是放在了 FlutterView 中捕获并传递给 Flutter ,如触摸、按键等等。
在 FlutterActivity 使用了代理模式,所有方法的实现都是在 FlutterActivityDelegate 中实现的。
FlutterActivityDelegate
FlutterActivityDelegate 实现了三个接口,分别是 FlutterActivityEvents 、FlutterView.Provider 和 PluginRegistry,都对应着 FlutterActivity 中的对应方法。
那么按照流程,初始化时会从调用 FlutterActivityDelegate.onCreate 开始。
FlutterActivityDelegate.onCreate()
onCreate 方法基本上完成了所有的初始化工作,从功能上说,主要是调用了以下几个方法。
- FlutterMain.ensureInitializationComplete()
- new FlutterView(Context, AttributeSet, FlutterNativeView)
- ceateLaunchView()
- loadIntent(Intent)
- runBundle(String)
FlutterMain.ensureInitializationComplete()
这个方法用于确定在 FlutterApplication.onCreate 阶段的初始化工作已经完成,
然后调用 FlutterJNI.nativeInit 进行初始化,在此之前获取了初始化所需的各参数,shellArgs 启动参数,kernelPath 内核地址,appStoragePath 应用文件地址,engineCachesPath 缓存地址。
FlutterJNI.nativeInit(Context, String[], String, String, String)
记录下各参数,并创建出 FlutterMain (c++)实例。
new FlutterView(Context, AttributeSet, FlutterNativeView)
创建一个 FlutterView 实例,在构造方法中主要执行了以下几个内容,分别是创建 FlutterNativeView ,
- new FlutterNativeView(Context)
- new FlutterRenderer(FlutterJNI)
- SurfaceHolder.Callback
- platform channels
- plugins
new FlutterNativeView(Context)
- FlutterPluginRegistry
- FlutterJNI
- DartExecutor
- attach(FlutterNativeView, boolean)
FlutterPluginRegistry
插件相关的工具,在 Android 和插件之间通信,给插件提供 Registrar 类,可以提供 Context ,注册一些回调方法,如 onActivityResult,当 FlutterActivity 被调用了这些方法时,则会辗转到此处,再传给所有需要的插件。
FlutterJNI
创建 FlutterJNI 实例。并给 FlutterJNI 设置了一个默认的 RenderSurface 。从 RenderSurface 中定义的方法看,它用于与 Flutter UI 交互。
DartExecutor
Dart 启动器,可以用于向 Dart 发送消息、启动 Dart 运行,不过还是依赖于 FlutterJNI 实现。
attach(FlutterNativeView, boolean)
此处会调用 AttachJNI 方法进入 c++ 层,底层只有一个函数,创建一个 AndroidShellHolder 实例。
然后调用 DartExecutor.onAttachedToJNI 给 FlutterJNI 设置 platformMessageHandler 。
AndroidShellHolder
构造函数中的逻辑:
Shell::CreateCallback<PlatformView> on_create_platform_view =
[is_background_view, java_object, &weak_platform_view](Shell& shell) {
std::unique_ptr<PlatformViewAndroid> platform_view_android;
if (is_background_view) {
platform_view_android = std::make_unique<PlatformViewAndroid>(
shell, // delegate
shell.GetTaskRunners(), // task runners
java_object // java object handle for JNI interop
);
} else {
platform_view_android = std::make_unique<PlatformViewAndroid>(
shell, // delegate
shell.GetTaskRunners(), // task runners
java_object, // java object handle for JNI interop
shell.GetSettings()
.enable_software_rendering // use software rendering
);
}
weak_platform_view = platform_view_android->GetWeakPtr();
return platform_view_android;
};
创建 on_create_platform_view 回调,用于创建 PlatformViewAndroid 实例。
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
};
创建 on_create_resterizer 回调看,用于创建 Rasterizer 实例。
fml::MessageLoop::EnsureInitializedForCurrentThread();
fml::RefPtr<fml::TaskRunner> gpu_runner;
fml::RefPtr<fml::TaskRunner> ui_runner;
fml::RefPtr<fml::TaskRunner> io_runner;
fml::RefPtr<fml::TaskRunner> platform_runner =
fml::MessageLoop::GetCurrent().GetTaskRunner();
if (is_background_view) {
auto single_task_runner = thread_host_.ui_thread->GetTaskRunner();
gpu_runner = single_task_runner;
ui_runner = single_task_runner;
io_runner = single_task_runner;
} else {
gpu_runner = thread_host_.gpu_thread->GetTaskRunner();
ui_runner = thread_host_.ui_thread->GetTaskRunner();
io_runner = thread_host_.io_thread->GetTaskRunner();
}
flutter::TaskRunners task_runners(thread_label, // label
platform_runner, // platform
gpu_runner, // gpu
ui_runner, // ui
io_runner // io
);
然后创建 TaskRunners 实例,传入参数时四个线程和一个 label ,这些都是在之前创建 thread_host_ 的时候创建出来的:
if (is_background_view) {
thread_host_ = {thread_label, ThreadHost::Type::UI};
} else {
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
ThreadHost::Type::IO};
}
对应的 ThreadHost 的构造函数如下:
ThreadHost::ThreadHost(std::string name_prefix, uint64_t mask) {
if (mask & ThreadHost::Type::Platform) {
platform_thread = std::make_unique<fml::Thread>(name_prefix + ".platform");
}
if (mask & ThreadHost::Type::UI) {
ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui");
}
if (mask & ThreadHost::Type::GPU) {
gpu_thread = std::make_unique<fml::Thread>(name_prefix + ".gpu");
}
if (mask & ThreadHost::Type::IO) {
io_thread = std::make_unique<fml::Thread>(name_prefix + ".io");
}
}
这四个线程分别对应着四种任务,不同的任务会放到不同的线程中去执行。
最后创建 Shell 实例:
shell_ =
Shell::Create(task_runners, // task runners
settings_, // settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
Shell::Create
创建 Shell 实例之前需要先初始化一些进程通用的 task ,然后再创建 DartVM 实例。
auto vm = DartVMRef::Create(settings);
所以先看下面的逻辑。
DartVM::Create
在这个函数中先调用 DartVMData::Create 创建 DartVMData 实例。
DataVMData::Create
先创建构造所需的参数:
- vm_snapshot
- isolate_snapshot
- shared_snapshot
它们都是 DartSnapshot 的实例,三个实例都是基于 Setting 创建,将 Setting 中的配置解析出来。
然后调用构造函数创建实例,将以上三个参数与 Setting 一起赋值给成员变量,DataVMData 本身可以看作是对 Setting 的解析,将 Settting 中的数据读取到三个变量中。
DartVM::Create
然后将 DartVMData 作为参数传递给构造函数。
new DartVM()
- 保存 Setting 变量 settings_
- 创建了一个线程池 concurrent_message_loop_
- 创建 skia 多线程任务执行器 skia_concurrent_executor_ ,使用了上一步创建的线程池
- 保存 DartVMData 变量 vm_data_
- 保存变量 isolate_name_server_
- 创建 ServiceProtocol 实例 service_protocol_ ,一个任务处理中介,本身没有实现处理逻辑,需要先添加 Handler ,然后来任务的时候找对应的 Handler 处理,或者任务本身带有处理逻辑
接着初始化一些列的参数,并创建了 Dart 实例,总的来说就是创建 Dart 虚拟机的过程,Flutter 用的是 Dart 语言,运行在 Dart VM 上,此处便是给 Flutter 初始化环境。
在初始化 Dart VM 的过程中还会建立 Dart 和 C++ 之间的联系,类似于 JNI ,注册了许多从 Dart 到 C++ 的函数调用,比如 Window :
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"Window_defaultRouteName", DefaultRouteName, 1, true},
{"Window_scheduleFrame", ScheduleFrame, 1, true},
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
{"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
{"Window_render", Render, 2, true},
{"Window_updateSemantics", UpdateSemantics, 2, true},
{"Window_setIsolateDebugName", SetIsolateDebugName, 2, true},
{"Window_reportUnhandledException", ReportUnhandledException, 2, true},
{"Window_setNeedsReportTimings", SetNeedsReportTimings, 2, true},
});
}
对应的 window.dart 中的 native 方法如void scheduleFrame() native 'Window_scheduleFrame';。
Shell::Create
完了再回到 Shell::Create 函数,下一步就是调用将 DartVM 作为参数进行 Shell 实例的创建。
接着判断 on_create_platform_view 和 on_create_rasterizer 是否为空,然后在 platform 线程调用 CreateShellOnPlatformThread 函数。
Shell::CreateShellOnPlatformThread
这个函数会先调用 Shell 的构造函数,在构造函数中 Shell 注册了许多 ServiceProtocolHandler ,然后调用 on_create_platform_view 和 on_create_rasterizer 两个回调函数创建 PlatformView 和 Rasterizer 实例,然后创建 Animator 和 Engine 实例。
Animator
Animator 的构造函数传入了三个参数,Shell 实例,taskRunner(可切换线程)和 VsyncWaiter 实例,而从其构造函数的实现来看,Shell 继承了 Delegate 类,起着回调的作用,主要的方法有 OnAnimatorBeginFrame 和 OnAnimatorDraw 等,tashRunner 用于切换线程,VsyncWaiter 是 PlatformView 提供的一个参数,它是平台相关的,在 Android 中 VsyncWaiter 的实现就依赖于 Choreographer ,用于请求下一帧并在帧到达时执行回调函数。
而 Animator 就作为 Shell 和 VsyncWaiter 的中介,从 VsyncWaiter 中获取帧相关的信息,再在合适的时候调用将结果传递给 Shell 。
Engine
然后将 Animator 实例作为参数创建 Engine 实例。Shell 也是 Engine 的 degelate ,在 Engine 的构造函数中主要创建了 ImageDecoder 和 RuntimeController 实例,前者用于解析 Image 的解析 ,后者用于处理 Dart 运行时一些相关的任务。
RuntimeController
RuntimeController 的构造函数中比较重要的有两个,一个是 Window 创建,一个是 DartIsolate 的创建。
Window 实例的创建需要一个 WindowClient 参数,这个参数也就是 RuntimeController 实例,Window 这个类,最重要的功能就是 C++ 和 Dart 的互相调用,之前在 Dart VM 创建的时候就已经完成了 Window 中 Dart 调用 C++ 函数的注册,这些函数都会转而调用 WindowClient 对应函数,也就是 RuntimeController 的对应函数。另外,当 C++ 需要调用 Dart 的函数时,也需要调用 Window 的方法,Window 会通过 tonic::DartInvokeField 调用 Dart 中的函数。
创建 DartIsolate 实例并将其 shared_ptr 保存在 unique_ptr 中,在 DartIsolate 构造函数中创建了 UIDartState 实例。
调用 DartIsolate::CreateDartVMAndEmbedderObjectPair 函数。
Engine 创建完毕之后,还需要执行 Shell::Setup 函数。
Shell::Setup
这个函数 Shell 只会执行一次,用于将 PlatformView、Engine、Rasterizer、IOManager 等赋值给 Shell 的成员变量。
以上整个过程就是 FlutterJNI.attachToNative 的操作,总的来说,算是完成了 Dart VM 的初始化,以及整个 Flutter 运行环境的创建,这是一个十分重量级的过程。
FlutterNativeView
FlutterNativeView 的构造方法也以 attach 方法的完成而结束,接着会回到 FlutterView 的构造方法。
FlutterView
创建完 FlutterNativeView 之后,下面会创建 FlutterRender ,这个类拥有一些与 Render 相关的功能,如监听 Flutter 是否展示,再比如获取当前 Flutter 的截屏。
后面的 FlutterNativeView.attachViewAndActivity 方法,将 FlutterView 和 FlutterActivity 传给 FlutterPluginRegistry ,这个类主要用于支持插件的开发。
创建 SurfaceHolder.Callback 实例。
创建两个监听器数组,可以给插件用,也可以自己用,LaunchView 机制就是通过 FirstFrameListener 实现的。
接着创建了 7 个 platform channel ,用于 Android 与 Flutter 之间的通信。以 LifecycleChannel 为例:
public class LifecycleChannel {
private static final String TAG = "LifecycleChannel";
@NonNull
public final BasicMessageChannel<String> channel;
public LifecycleChannel(@NonNull DartExecutor dartExecutor) {
this.channel = new BasicMessageChannel<>(dartExecutor, "flutter/lifecycle", StringCodec.INSTANCE);
}
public void appIsInactive() {
Log.v(TAG, "Sending AppLifecycleState.inactive message.");
channel.send("AppLifecycleState.inactive");
}
public void appIsResumed() {
Log.v(TAG, "Sending AppLifecycleState.resumed message.");
channel.send("AppLifecycleState.resumed");
}
public void appIsPaused() {
Log.v(TAG, "Sending AppLifecycleState.paused message.");
channel.send("AppLifecycleState.paused");
}
}
内部使用 BasicMessageChannel 做通信基础,有三个生命周期的方法,在 FlutterActivity 的对应生命周期则会调用对应的方法通知 Flutter 。
下面是一系列插件的创建,TextInputPlugin 用于接收 Flutter 关于键盘操作的信息,打开或关闭键盘,AndroidKeyProcessor 用于将 Android 的 KeyEvent 分发给 Flutter ,AndroidTouchProcessor 用于将 Android 的 TouchEvent 分发给 Flutter 。
最后将 Android 中的一些配置传给 Flutter 。至此,FlutterView 的创建完毕,可以看到,主要还是进行 Flutter 运行环境的初始化,及 Android 与 Flutter 通信基础的初始化。
FlutterActivityDelegate.onCreate
回到 FlutterActivityDelegate.onCreate 方法,下一步是创建 LaunchView ,LaunchView 就是启动页,因为启动 Flutter 应用的时候需要进行大量的初始化,所以如果没有启动页则会有一段很明显的黑屏时间,为了解决这个问题,FlutterActivity 启动之后会先加载一个 LaunchView ,知道 Flutter 环境创建完毕开始运行的时候,LaunchView 会被移除,转而显示 FlutterView 的内容。
LaunchView 本质上就是一个 View ,启动页的内容并不是 Android 控件,而是一张背景图,需要开发者主动添加到 Android 项目中去。而 LaunchView 移除的时机,就是 Flutter 第一帧开始绘制的时候,上面说到过 FlutterView 会注册 FirstFrameListener 监听器,目的就是能够在这个时候移除 LaunchView 。
FlutterActivityDelegate.runBundle
准备工作就绪,下一步就是启动 Flutter 应用。
首先调用的是 loadIntent 方法,会先从当前 FlutterActivity 的 Intent 中查找是否有启动参数,主要还是 router 和 appBundlePath ,分别表示 Flutter 的资源文件地址和默认路由。默认的路由获取之后通过 NavigationChannel 调用 C++ 函数将这个默认参数保存起来,以供之后 Flutter 使用,而从 C++ 中的 Engine::DefaultRouteName 函数也可以看出,默认路由是 ‘/’,
std::string Engine::DefaultRouteName() {
if (!initial_route_.empty()) {
return initial_route_;
}
return "/";
}
接着就调用 runBundlePath ,在此之前需要先获取 appBundlePath ,先从 Intent 中看是否用用户指定的地址,没有,则通过 FlutterMain.findAppBundlePath 获取默认的地址,
private void runBundle(String appBundlePath) {
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
FlutterRunArguments args = new FlutterRunArguments();
args.bundlePath = appBundlePath;
args.entrypoint = "main";
flutterView.runFromBundle(args);
}
}
entryPoint 正是 Flutter 应用的启动函数,即 main 函数,最终调用 FlutterJNI.nativeRunBundleAndSnapshotFromLibrary 从 C++ 中启动。
RunBundleAndSnapshotFromLibrary
将 RunBundleAndSnapshotFromLibrary 传递的参数封装到 RunConfiguration 中后,接着调用 AndroidShellHolder::Launch ,经过一系列的调用之后,最终会调用 DartIsolate::RunFromLibrary,这个函数中会调用 InvokeMainEntrypoint 函数完成对 Dart main 函数的调用,由此进入 Flutter 的领域。Flutter 先建立好自身运营所需的环境之后,便通过与 C++ 互相调用的方法,利用 C++ 作为与 native 的中介,获取 native 上的一些服务,具体到 Android 上的话,就是 Choreographer 、TouchEvent 等,另外,画面的绘制等工作,也会交给 C++ 完成,还有可以为 Flutter 提供更多 native 功能的插件,为其提供服务 MethodChannel ,只是一种封装
GeneratedPluginRegistrant.registerWith(PluginRegistry)
这个方法会在 FlutterActivity 的 onCreate 方法中调用,GeneratedPluginRegistrant 是自动生成的一个类,用于注册所有在 pubspec.yaml 中声明的 Flutter 插件,比如 shared_preference 插件,生成的类就是这样的:
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin"));
}
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
final String key = GeneratedPluginRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) {
return true;
}
registry.registrarFor(key);
return false;
}
先判断是否已经注册过插件,然后执行插件的 registerWith 方法,这个方法将由插件实现,这也是插件必须实现的一个方法。