接上回 Flutter——在Android平台上的启动流程浅析,
我们来看看穿插在其中的native层都做了什么。
由于代码较多,我会将说明以注释的形式写在代码里,并删除非必要代码
在flutterLoader中的这个startInitialization()方法中:
public void startInitialization(@NonNull Context applicationContext, @NonNull FlutterLoader.Settings settings) {
if (this.settings == null) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
} else {
....
Callable initTask = new Callable() {
public FlutterLoader.InitResult call() {
....
///这里是在子线程执行的
System.loadLibrary("flutter");
....
return new FlutterLoader.InitResult(PathUtils.getFilesDir(appContext), PathUtils.getCacheDirectory(appContext), PathUtils.getDataDirectory(appContext));
}
};
this.initResultFuture = Executors.newSingleThreadExecutor().submit(initTask);
}
}
}
System.loadLibrary(“flutter”);并不是简单地加载flutter框架代码,它最终会进入native中的JNI_OnLoad方法:
// This is called by the VM when the shared library is first loaded.
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// 初始化 JVM (只是将虚拟机进行一个保存)
// 之后关联到当前线程上
fml::jni::InitJavaVM(vm);
JNIEnv* env = fml::jni::AttachCurrentThread();
bool result = false;
// 注册 FlutterMain.
result = flutter::FlutterMain::Register(env);
FML_CHECK(result);
// 注册 PlatformView
// 这里会注册大量的方法,使c++和java可以互相调用
result = flutter::PlatformViewAndroid::Register(env);
FML_CHECK(result);
// 注册 VSyncWaiter.
// 这里将java的VSyncWaiter类中的方法与
// native中的VsyncWaiterAndroid的映射,便可以互相调用
result = flutter::VsyncWaiterAndroid::Register(env);
FML_CHECK(result);
return JNI_VERSION_1_4;
}
tip:PlatformViewAndroid路径为:engine/shell/platform/android
有兴趣的话,可以看看
整体来看,这里主要是保存了jvm,同时对c++和java的方法进行了映射以便双方可以互相调用。
至此FlutterApplication中所拉起的native代码就简单概括完了,我们接着FlutterActivity中所调用native代码。
这里需要提一下,目前你搜索FlutterActivity这个类,会发现有两个:
android/FlutterActivity 这个是最新的
app/FlutterActivity 已过期
经过一系列调用,具体见这篇文章:
Flutter——在Android平台上的启动流程浅析,
会初始化flutterEngine,构造函数如下:
//很长,但是其中初始化的东西还是比较有用的
//所以我觉得有必要贴一下
/** Fully configurable {@code FlutterEngine} constructor. */
public FlutterEngine(
@NonNull Context context,
@NonNull FlutterLoader flutterLoader,
@NonNull FlutterJNI flutterJNI,
@NonNull PlatformViewsController platformViewsController,
@Nullable String[] dartVmArgs,
boolean automaticallyRegisterPlugins,
boolean waitForRestorationData) {
this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
this.dartExecutor.onAttachedToJNI();
accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI);
keyEventChannel = new KeyEventChannel(dartExecutor);
lifecycleChannel = new LifecycleChannel(dartExecutor);
localizationChannel = new LocalizationChannel(dartExecutor);
mouseCursorChannel = new MouseCursorChannel(dartExecutor);
navigationChannel = new NavigationChannel(dartExecutor);
platformChannel = new PlatformChannel(dartExecutor);
restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData);
settingsChannel = new SettingsChannel(dartExecutor);
systemChannel = new SystemChannel(dartExecutor);
textInputChannel = new TextInputChannel(dartExecutor);
this.localizationPlugin = new LocalizationPlugin(context, localizationChannel);
this.flutterJNI = flutterJNI;
flutterLoader.startInitialization(context.getApplicationContext());
///注意这里
flutterLoader.ensureInitializationComplete(context, dartVmArgs);
flutterJNI.addEngineLifecycleListener(engineLifecycleListener);
flutterJNI.setPlatformViewsController(platformViewsController);
flutterJNI.setLocalizationPlugin(localizationPlugin);
attachToJni();
// TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if
// possible.
this.renderer = new FlutterRenderer(flutterJNI);
this.platformViewsController = platformViewsController;
this.platformViewsController.onAttachedToJNI();
this.pluginRegistry =
new FlutterEnginePluginRegistry(context.getApplicationContext(), this, flutterLoader);
if (automaticallyRegisterPlugins) {
registerPlugins();
}
}
整个构造函数会初始化大量channel,同时进行一些native方法注册,其中:
flutterLoader.ensureInitializationComplete(context, dartVmArgs);
会转到native,详细代码如下:
///此方法会阻塞,直到native 系统工作执行完毕
public void ensureInitializationComplete(
@NonNull Context applicationContext, @Nullable String[] args) {
if (initialized) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException(
"ensureInitializationComplete must be called on the main thread");
}
if (settings == null) {
throw new IllegalStateException(
"ensureInitializationComplete must be called after startInitialization");
}
///收集各种文件路径
try {
InitResult result = initResultFuture.get();
List shellArgs = new ArrayList<>();
shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
ApplicationInfo applicationInfo = getApplicationInfo(applicationContext);
shellArgs.add(
"--icu-native-lib-path="
+ applicationInfo.nativeLibraryDir
+ File.separator
+ DEFAULT_LIBRARY);
if (args != null) {
Collections.addAll(shellArgs, args);
}
String kernelPath = null;
if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
String snapshotAssetPath = result.dataDirPath + File.separator + flutterAssetsDir;
kernelPath = snapshotAssetPath + File.separator + DEFAULT_KERNEL_BLOB;
shellArgs.add("--" + SNAPSHOT_ASSET_PATH_KEY + "=" + snapshotAssetPath);
shellArgs.add("--" + VM_SNAPSHOT_DATA_KEY + "=" + vmSnapshotData);
shellArgs.add("--" + ISOLATE_SNAPSHOT_DATA_KEY + "=" + isolateSnapshotData);
} else {
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName);
// Most devices can load the AOT shared library based on the library name
// with no directory path. Provide a fully qualified path to the library
// as a workaround for devices where that fails.
shellArgs.add(
"--"
+ AOT_SHARED_LIBRARY_NAME
+ "="
+ applicationInfo.nativeLibraryDir
+ File.separator
+ aotSharedLibraryName);
}
shellArgs.add("--cache-dir-path=" + result.engineCachesPath);
if (settings.getLogTag() != null) {
shellArgs.add("--log-tag=" + settings.getLogTag());
}
long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
// TODO(cyanlaz): Remove this when dynamic thread merging is done.
// https://github.com/flutter/flutter/issues/59930
Bundle bundle = applicationInfo.metaData;
if (bundle != null) {
boolean use_embedded_view = bundle.getBoolean("io.flutter.embedded_views_preview");
if (use_embedded_view) {
shellArgs.add("--use-embedded-view");
}
}
/// 拉起native
FlutterJNI.nativeInit(
applicationContext,
shellArgs.toArray(new String[0]),
kernelPath,
result.appStoragePath,
result.engineCachesPath,
initTimeMillis);
initialized = true;
} catch (Exception e) {
Log.e(TAG, "Flutter initialization failed.", e);
throw new RuntimeException(e);
}
}
这里会将相关的信息通过FlutterJNI.nativeInit,即:
///native 方法
public static native void nativeInit(
@NonNull Context context,
@NonNull String[] args,
@Nullable String bundlePath,
@NonNull String appStoragePath,
@NonNull String engineCachesPath,
long initTimeMillis);
传递到native层,还记得上部分我们注册的flutterMain方法吗?
bool FlutterMain::Register(JNIEnv* env) {
static const JNINativeMethod methods[] = {
{
///看这里 name是方法名的意思
.name = "nativeInit",
.signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
"lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
///方法&Init的地址被保存在了fnPtr上
.fnPtr = reinterpret_cast(&Init),
},
{
.name = "nativePrefetchDefaultFontManager",
.signature = "()V",
.fnPtr = reinterpret_cast(&PrefetchDefaultFontManager),
},
};
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
if (clazz == nullptr) {
return false;
}
return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
}
通过指针.fnPtr = reinterpret_cast
void FlutterMain::Init(JNIEnv* env,
jclass clazz,
jobject context,
jobjectArray jargs,
jstring kernelPath,
jstring appStoragePath,
jstring engineCachesPath,
jlong initTimeMillis) {
std::vector args;
///tag
args.push_back("flutter");
///将上面我们收集的那些路径信息保存到 args中
///以‘j’ 表示java传过来的。
for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
args.push_back(std::move(arg));
}
auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
auto settings = SettingsFromCommandLine(command_line);
///engine启动时间
int64_t init_time_micros = initTimeMillis * 1000;
settings.engine_start_timestamp =
std::chrono::microseconds(Dart_TimelineGetMicros() - init_time_micros);
// Restore the callback cache.
// TODO(chinmaygarde): Route all cache file access through FML and remove this
// setter.
flutter::DartCallbackCache::SetCachePath(
fml::jni::JavaStringToString(env, appStoragePath));
///初始化缓存路径
fml::paths::InitializeAndroidCachesPath(
fml::jni::JavaStringToString(env, engineCachesPath));
///加载缓存
flutter::DartCallbackCache::LoadCacheFromDisk();
if (!flutter::DartVM::IsRunningPrecompiledCode() && kernelPath) {
// Check to see if the appropriate kernel files are present and configure
// settings accordingly.
auto application_kernel_path =
fml::jni::JavaStringToString(env, kernelPath);
if (fml::IsFile(application_kernel_path)) {
settings.application_kernel_asset = application_kernel_path;
}
}
settings.task_observer_add = [](intptr_t key, fml::closure callback) {
fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
};
settings.task_observer_remove = [](intptr_t key) {
fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
};
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
// There are no ownership concerns here as all mappings are owned by the
// embedder and not the engine.
auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
return [mapping, size]() {
return std::make_unique(mapping, size);
};
};
settings.dart_library_sources_kernel =
make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
// Not thread safe. Will be removed when FlutterMain is refactored to no
// longer be a singleton.
g_flutter_main.reset(new FlutterMain(std::move(settings)));
g_flutter_main->SetupObservatoryUriCallback(env);
}
以上主要是对java传过来的数据进行保存,至此由flutterLoader.ensureInitializationComplete所引起的native执行完毕,
在其后面会执行attachToJni()。
attachToJni()最终会调用flutterJNI.attachToNative(false):
///这步完成后,android便可以与engine通信了
@UiThread
public void attachToNative(boolean isBackgroundView) {
ensureRunningOnMainThread();
ensureNotAttachedToNative();
nativePlatformViewId = nativeAttach(this, isBackgroundView);
}
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
此方法会调用native的:
static jlong AttachJNI(JNIEnv* env,
jclass clazz,
jobject flutterJNI,
jboolean is_background_view) {
fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
std::shared_ptr jni_facade =
std::make_shared(java_object);
///主要就是初始化一个 shell holder
auto shell_holder = std::make_unique(
FlutterMain::Get().GetSettings(), jni_facade, is_background_view);
if (shell_holder->IsValid()) {
return reinterpret_cast(shell_holder.release());
} else {
return 0;
}
}
我们来看一下AndroidShellHolder.cc的实现
它有一个100多行的构造函数:
AndroidShellHolder::AndroidShellHolder(
flutter::Settings settings,
std::shared_ptr jni_facade,
bool is_background_view)
: settings_(std::move(settings)), jni_facade_(jni_facade) {
static size_t shell_count = 1;
auto thread_label = std::to_string(shell_count++);
FML_CHECK(pthread_key_create(&thread_destruct_key_, ThreadDestructCallback) ==
0);
///这里我们传递的是false
if (is_background_view) {
thread_host_ = {thread_label, ThreadHost::Type::UI};
} else {
/// 会创建三个线程 分别是 UI\GPU\IO
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
ThreadHost::Type::IO};
}
// Detach from JNI when the UI and raster threads exit.
// UI和raster线程退出时,与JNI分离
// raster就是gpu线程,它将我们的绘制指令转为gpu指令
auto jni_exit_task([key = thread_destruct_key_]() {
FML_CHECK(pthread_setspecific(key, reinterpret_cast(1)) == 0);
});
thread_host_.ui_thread->GetTaskRunner()->PostTask(jni_exit_task);
if (!is_background_view) {
thread_host_.raster_thread->GetTaskRunner()->PostTask(jni_exit_task);
}
fml::WeakPtr weak_platform_view;
Shell::CreateCallback on_create_platform_view =
[is_background_view, &jni_facade, &weak_platform_view](Shell& shell) {
std::unique_ptr platform_view_android;
if (is_background_view) {
...走下面
} else {
///初始化了一个PlatformViewAndroid
platform_view_android = std::make_unique(
shell, // delegate
shell.GetTaskRunners(), // task runners
jni_facade, // JNI interop
shell.GetSettings()
.enable_software_rendering // use software rendering
);
}
weak_platform_view = platform_view_android->GetWeakPtr();
shell.OnDisplayUpdates(DisplayUpdateType::kStartup,
{Display(jni_facade->GetDisplayRefreshRate())});
return platform_view_android;
};
Shell::CreateCallback on_create_rasterizer = [](Shell& shell) {
return std::make_unique(shell);
};
// The current thread will be used as the platform thread. Ensure that the
// message loop is initialized.
// 初始化native的 message loop
// gpu/ui/io它们也有各自的 msg loop
fml::MessageLoop::EnsureInitializedForCurrentThread();
///初始化对应线程的task runner
/// 这样我们便可以向指定线程post 任务
fml::RefPtr gpu_runner;
fml::RefPtr ui_runner;
fml::RefPtr io_runner;
fml::RefPtr 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_.raster_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, // raster
ui_runner, // ui
io_runner // io
);
///提高ui 和 gpu线程等级
///线程值 越小 等级越高
task_runners.GetRasterTaskRunner()->PostTask([]() {
// Android describes -8 as "most important display threads, for
// compositing the screen and retrieving input events". Conservatively
// set the raster thread to slightly lower priority than it.
if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
// Defensive fallback. Depending on the OEM, it may not be possible
// to set priority to -5.
if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
FML_LOG(ERROR) << "Failed to set GPU task runner priority";
}
}
});
task_runners.GetUITaskRunner()->PostTask([]() {
if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
FML_LOG(ERROR) << "Failed to set UI task runner priority";
}
});
///创建shell
shell_ =
Shell::Create(task_runners, // task runners
GetDefaultPlatformData(), // window data
settings_, // settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
platform_view_ = weak_platform_view;
FML_DCHECK(platform_view_);
is_valid_ = shell_ != nullptr;
}
我们接着看一下 shell_的创建:
std::unique_ptr Shell::Create(
TaskRunners task_runners,
const PlatformData platform_data,
Settings settings,
Shell::CreateCallback on_create_platform_view,
Shell::CreateCallback on_create_rasterizer) {
PerformInitializationTasks(settings);
PersistentCache::SetCacheSkSL(settings.cache_sksl);
TRACE_EVENT0("flutter", "Shell::Create");
///创建虚拟机
auto vm = DartVMRef::Create(settings);
FML_CHECK(vm) << "Must be able to initialize the VM.";
auto vm_data = vm->GetVMData();
return Shell::Create(std::move(task_runners), //
std::move(platform_data), //
std::move(settings), //
vm_data->GetIsolateSnapshot(), // isolate snapshot
on_create_platform_view, //
on_create_rasterizer, //
std::move(vm) //
);
}
DartVMRef DartVMRef::Create(Settings settings,
fml::RefPtr vm_snapshot,
fml::RefPtr isolate_snapshot) {
std::scoped_lock lifecycle_lock(gVMMutex);
...删除一些代码
//这里对已有的虚拟机进行复用
if (auto vm = gVM.lock()) {
FML_DLOG(WARNING) << "Attempted to create a VM in a process where one was "
"already running. Ignoring arguments for current VM "
"create call and reusing the old VM.";
// There was already a running VM in the process,
return DartVMRef{std::move(vm)};
}
...删除一些代码
//如果没有,就重新创建一个虚拟机
auto isolate_name_server = std::make_shared();
auto vm = DartVM::Create(std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
isolate_name_server //
);
...删除一些代码
return DartVMRef{std::move(vm)};
}
我们继续看shell的创建,最终会调用CreateShellOnPlatformThread。
std::unique_ptr Shell::CreateShellOnPlatformThread(
DartVMRef vm,
TaskRunners task_runners,
const PlatformData platform_data,
Settings settings,
fml::RefPtr isolate_snapshot,
const Shell::CreateCallback& on_create_platform_view,
const Shell::CreateCallback& on_create_rasterizer) {
...
///创建对象
auto shell =
std::unique_ptr(new Shell(std::move(vm), task_runners, settings));
// 创建rasterizer :工作在gpu线程
// 这里要说一下,gpu线程还是在cpu上的,只是这个线程叫gpu 而已
std::promise> rasterizer_promise;
auto rasterizer_future = rasterizer_promise.get_future();
std::promise> snapshot_delegate_promise;
auto snapshot_delegate_future = snapshot_delegate_promise.get_future();
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetRasterTaskRunner(), [&rasterizer_promise, //
&snapshot_delegate_promise,
on_create_rasterizer, //
shell = shell.get() //
]() {
TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem");
std::unique_ptr rasterizer(on_create_rasterizer(*shell));
snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate());
rasterizer_promise.set_value(std::move(rasterizer));
});
// 在当前线程(platform thread)创建platform view.
auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return nullptr;
}
// Ask the platform view for the vsync waiter. This will be used by the engine
// to create the animator.
auto vsync_waiter = platform_view->CreateVSyncWaiter();
if (!vsync_waiter) {
return nullptr;
}
...删除部分代码...
///通过向 io线程post task 来创建 io manager
fml::TaskRunner::RunNowOrPostTask(
io_task_runner,
[&io_manager_promise, //
&weak_io_manager_promise, //
&unref_queue_promise, //
platform_view = platform_view->GetWeakPtr(), //
io_task_runner, //
is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch() //
]() {
TRACE_EVENT0("flutter", "ShellSetupIOSubsystem");
auto io_manager = std::make_unique(
platform_view.getUnsafe()->CreateResourceContext(),
is_backgrounded_sync_switch, io_task_runner);
weak_io_manager_promise.set_value(io_manager->GetWeakPtr());
unref_queue_promise.set_value(io_manager->GetSkiaUnrefQueue());
io_manager_promise.set_value(std::move(io_manager));
});
// Send dispatcher_maker to the engine constructor because shell won't have
// platform_view set until Shell::Setup is called later.
auto dispatcher_maker = platform_view->GetDispatcherMaker();
// 在ui线程创建engine
// 这里的engine指针被跨线程使用
std::promise> engine_promise;
auto engine_future = engine_promise.get_future();
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
fml::MakeCopyable([&engine_promise, //
shell = shell.get(), //
&dispatcher_maker, //
&platform_data, //
isolate_snapshot = std::move(isolate_snapshot), //
vsync_waiter = std::move(vsync_waiter), //
&weak_io_manager_future, //
&snapshot_delegate_future, //
&unref_queue_future //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
const auto& task_runners = shell->GetTaskRunners();
// 创建animator(ui线程)
auto animator = std::make_unique(*shell, task_runners,
std::move(vsync_waiter));
engine_promise.set_value(std::make_unique(
*shell, //
dispatcher_maker, //
*shell->GetDartVM(), //
std::move(isolate_snapshot), //
task_runners, //
platform_data, //
shell->GetSettings(), //
std::move(animator), //
weak_io_manager_future.get(), //
unref_queue_future.get(), //
snapshot_delegate_future.get() //
));
}));
if (!shell->Setup(std::move(platform_view), //
engine_future.get(), //
rasterizer_future.get(), //
io_manager_future.get()) //
) {
return nullptr;
}
return shell;
}
由于代码太长,这里再汇总一下:
shell初始化之后,还有分别在io/ui/gpu/platform线程创建以下对象:
rasterizer 在gpu线程工作,负责将绘制指令转为gpu指令
platform view 在当前线程(platform thread)
engine 和 animator 在ui线程工作
flutter最终会通过animator向platformView 申请VSync信号
接下来我们再看一下上面代码中对engine的初始化。
代码相对较少,但是连接的东西非常多:
Engine::Engine(Delegate& delegate,
const PointerDataDispatcherMaker& dispatcher_maker,
DartVM& vm,
fml::RefPtr isolate_snapshot,
TaskRunners task_runners,
const PlatformData platform_data,
Settings settings,
std::unique_ptr animator,
fml::WeakPtr io_manager,
fml::RefPtr unref_queue,
fml::WeakPtr snapshot_delegate)
: Engine(delegate,
dispatcher_maker,
vm.GetConcurrentWorkerTaskRunner(),
task_runners,
settings,
std::move(animator),
io_manager,
nullptr) {
runtime_controller_ = std::make_unique(
*this, // runtime delegate
&vm, // VM
std::move(isolate_snapshot), // isolate snapshot
task_runners_, // task runners
std::move(snapshot_delegate), // snapshot delegate
GetWeakPtr(), // hint freed delegate
std::move(io_manager), // io manager
std::move(unref_queue), // Skia unref queue
image_decoder_.GetWeakPtr(), // image decoder
settings_.advisory_script_uri, // advisory script uri
settings_.advisory_script_entrypoint, // advisory script entrypoint
settings_.idle_notification_callback, // idle notification callback
platform_data, // platform data
settings_.isolate_create_callback, // isolate create callback
settings_.isolate_shutdown_callback, // isolate shutdown callback
settings_.persistent_isolate_data // persistent isolate data
);
}
就是创建了一个runtime_controller_ ,你可以将runtime controller 看做native、platform和flutter的一个纽带。
经过上面一系列的代码,可能有点晕,概括来讲Flutter Activity在注册flutterMain过程中会创建初始化shell,而在这个初始化的过程中,我们分别会创建三个线程,算上当前线程的话,就是4个:
并初始化一系列重要对象。
好的,我们再回到主线,onCreate()已经过了,下面我们可以看一下onStart()生命周期:
Flutter——在Android平台上的启动流程浅析
此方法会调用 delegate.onStart(); 并最终调用FlutterJNI的native方法:
private native void nativeRunBundleAndSnapshotFromLibrary(
long nativePlatformViewId,
@NonNull String bundlePath,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager manager);
从这里开始,其终点就是执行dart的代码。
接着我们看一下native方法:
(位置在platform_view_android_jni_impl.cc)
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jstring jBundlePath,
jstring jEntrypoint,
jstring jLibraryUrl,
jobject jAssetManager) {
...删除部分代码
///这里主要是根据参数,生成一个config 并用于启动
/// 我们的 默认启动入口 'main()'就在这个config里
ANDROID_SHELL_HOLDER->Launch(std::move(config));
}
我们接着看Launch(std::move(config));方法:
void AndroidShellHolder::Launch(RunConfiguration config) {
if (!IsValid()) {
return;
}
shell_->RunEngine(std::move(config));
}
又调用了 run engine 方法:
void Shell::RunEngine(
RunConfiguration run_configuration,
const std::function& result_callback) {
...删除一些代码
///向 ui线程post了一个任务
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable(
[run_configuration = std::move(run_configuration),
weak_engine = weak_engine_, result]() mutable {
if (!weak_engine) {
FML_LOG(ERROR)
<< "Could not launch engine with configuration - no engine.";
result(Engine::RunStatus::Failure);
return;
}
///调用engine的run方法
auto run_result = weak_engine->Run(std::move(run_configuration));
if (run_result == flutter::Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch engine with configuration.";
}
result(run_result);
}));
}
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
if (!configuration.IsValid()) {
FML_LOG(ERROR) << "Engine run configuration was invalid.";
return RunStatus::Failure;
}
///获取要执行的 dart代码入口点
///这里就是 main方法 from mian.dart
last_entry_point_ = configuration.GetEntrypoint();
last_entry_point_library_ = configuration.GetEntrypointLibrary();
....
///调用了LaunchRootIsolate方法
if (!runtime_controller_->LaunchRootIsolate(
settings_, //
configuration.GetEntrypoint(), //
configuration.GetEntrypointLibrary(), //
configuration.TakeIsolateConfiguration()) //
) {
return RunStatus::Failure;
}
...删除部分代码
return Engine::RunStatus::Success;
}
bool RuntimeController::LaunchRootIsolate(
const Settings& settings,
std::optional dart_entrypoint,
std::optional dart_entrypoint_library,
std::unique_ptr isolate_configuration) {
if (root_isolate_.lock()) {
FML_LOG(ERROR) << "Root isolate was already running.";
return false;
}
///创建一个 ‘运行’的 root isolate
auto strong_root_isolate =
DartIsolate::CreateRunningRootIsolate(
settings, // 配置
isolate_snapshot_, // 快照
task_runners_, //
std::make_unique(this), // 平台配置
snapshot_delegate_, //
hint_freed_delegate_, //
io_manager_, // io管理运行在Io线程
unref_queue_, //
image_decoder_, // 图片解码
advisory_script_uri_, //
advisory_script_entrypoint_, //
DartIsolate::Flags{}, //
isolate_create_callback_, //
isolate_shutdown_callback_, //
dart_entrypoint, // 入口 方法(main.dart)
dart_entrypoint_library, // 入口库
std::move(isolate_configuration) //
)
.lock();
...删除部分代码
return true;
}
我们看一下DartIsolate的CreateRunningRootIsolate方法
std::weak_ptr DartIsolate::CreateRunningRootIsolate(
const Settings& settings,
fml::RefPtr isolate_snapshot,
TaskRunners task_runners,
std::unique_ptr platform_configuration,
fml::WeakPtr snapshot_delegate,
fml::WeakPtr hint_freed_delegate,
fml::WeakPtr io_manager,
fml::RefPtr skia_unref_queue,
fml::WeakPtr image_decoder,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
Flags isolate_flags,
const fml::closure& isolate_create_callback,
const fml::closure& isolate_shutdown_callback,
std::optional dart_entrypoint,
std::optional dart_entrypoint_library,
std::unique_ptr isolate_configration) {
...删除代码
///这里创建了一个 isolate 但是非运行的
auto isolate = CreateRootIsolate(settings, //
isolate_snapshot, //
task_runners, //
std::move(platform_configuration), //
snapshot_delegate, //
hint_freed_delegate, //
io_manager, //
skia_unref_queue, //
image_decoder, //
advisory_script_uri, //
advisory_script_entrypoint, //
isolate_flags, //
isolate_create_callback, //
isolate_shutdown_callback //
)
.lock();
...删除部分代码 (主要是对 isolate的状态检查)
//注意这个方法
if (!isolate->RunFromLibrary(dart_entrypoint_library, //
dart_entrypoint, //
settings.dart_entrypoint_args //
)) {
FML_LOG(ERROR) << "Could not run the run main Dart entrypoint.";
return {};
}
if (settings.root_isolate_shutdown_callback) {
isolate->AddIsolateShutdownCallback(
settings.root_isolate_shutdown_callback);
}
shutdown_on_error.Release();
return isolate;
}
创建isolate后,进一步调用RunFromLibrary 这个方法:
tip:注意这个过程携带的参数。
bool DartIsolate::RunFromLibrary(std::optional library_name,
std::optional entrypoint,
const std::vector& args) {
TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary");
/// isolate 非准备状态,直接退出
if (phase_ != Phase::Ready) {
return false;
}
tonic::DartState::Scope scope(this);
...删除部分代码
///这里进一步调用了 InvokeMainEntrypoint方法
if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
return false;
}
///设置 isolate为 运行状态
phase_ = Phase::Running;
return true;
}
InvokeMainEntrypoint:
[[nodiscard]] static bool InvokeMainEntrypoint(
Dart_Handle user_entrypoint_function,
Dart_Handle args) {
...删除部分代码
///这里,会通过DartInvokeField
///拉起我们的 main.dart中的main()方法并开始flutter的运行
/// PS :这个入口点也可以自定义,不过很少用到
if (tonic::LogIfError(tonic::DartInvokeField(
Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMainZoned",
{start_main_isolate_function, user_entrypoint_function, args}))) {
FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
return false;
}
return true;
}
到了这里,整个flutter的启动从平台到native所作的工作基本就简要的介绍完了。
本人也是刚开始对native进行了解,以进一步对flutter的运行原理有所了解,如果有错误之处,还请指出,谢谢。
Flutter 仿网易云音乐App
Flutter&Android 启动页(闪屏页)的加载流程和优化方案
Flutter版 仿.知乎列表的视差效果
Flutter——实现网易云音乐的渐进式卡片切换
Flutter 仿同花顺自选股列表