微信公眾號:Android部落格,文末有二維碼
個人網(wǎng)站:chengang.plus
啟動過程分析
原圖地址是:https://ftp.bmp.ovh/imgs/2020/04/f92a2d6c47bcf3f6.jpg
1、 初始化
一般的,都有一個入口Activity俘枫,這個Activity繼承自FlutterActivity赫蛇。
從入口Activity的oncreate方法開始分析,首先調(diào)用FlutterMain.startInitialization(this)
矿卑,如果我們自定義了Application(FlutterApplication),可以在Application的onCreate方法中調(diào)用悄但。
startInitialization最終會調(diào)用到FlutterLoader的startInitialization方法棠隐,在這個方法中主要干了以下幾件事:
- 初始化系統(tǒng)配置
- 在debug或JIT模式下復(fù)制assert文件夾下的文件到data目錄下。從apk包的assets目錄下檐嚣,將vm_snapshot_data,isolate_snapshot_data,kernel_blob.bin文件復(fù)制到/data/data/package name/app_flutter/flutter_assets/目錄下助泽。
- 加載libflutter.so庫
- 計算初始化時間,并傳遞到native層
初始化操作為之后運行準(zhǔn)備了flutter環(huán)境嚎京,也準(zhǔn)備好了運行所需要的資源
2嗡贺、創(chuàng)建FlutterView
創(chuàng)建過程中比較重要的幾行代碼如下:
io\flutter\view\FlutterView.java
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
mNativeView = new FlutterNativeView(activity.getApplicationContext());
mNativeView.attachViewAndActivity(this, activity);
mSurfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface());
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mNativeView.getFlutterJNI().onSurfaceChanged(width, height);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mNativeView.getFlutterJNI().onSurfaceDestroyed();
}
};
}
其中涉及FlutterActivity
,FlutterView
鞍帝,FlutterNativeView
诫睬,FlutterActivityDelegate
,FlutterJNI
這幾個主要的類膜眠。
- FlutterActivity主要處理各個生命周期以及各種系統(tǒng)回調(diào)。
- FlutterView其實是一個SurfaceView溜嗜,在SurfaceHolder.Callback中處理View的各個狀態(tài)宵膨,這關(guān)系到整個界面的展現(xiàn)。
- FlutterNativeView其實不是個View炸宵,只是一個中間人辟躏。因為他持有FlutterJNI和DartExecutor對象,將View的狀態(tài)和消息傳遞到native層
- FlutterActivityDelegate土全,代理捎琐。創(chuàng)建了FlutterView和FlutterNativeView,然后將Activity的生命周期和各種回調(diào)給到FlutterView處理
- FlutterJNI裹匙,被FlutterView調(diào)用瑞凑,然后調(diào)用native代碼,并接收native的回調(diào)
2.1 創(chuàng)建FlutterNativeView
主要的幾行代碼如下:
io\flutter\view\FlutterNativeView.java
public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
mFlutterJNI = new FlutterJNI();
mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this, isBackgroundView);
}
2.1.1 先持有FlutterJNI對象概页,后續(xù)用于與native交互
2.1.2 attach
最終調(diào)用到了FlutterJNI的attachToNative方法籽御,并調(diào)用native的nativeAttach方法《璩祝看看這個nativeAttach方法注冊的地方:
shell\platform\android\platform_view_android_jni.cc
{
.name = "nativeAttach",
.signature = "(Lio/flutter/embedding/engine/FlutterJNI;Z)J",
.fnPtr = reinterpret_cast<void*>(&AttachJNI),
}
被注冊到了AttachJNI方法技掏,看看這個方法:
shell\platform\android\platform_view_android_jni.cc
static jlong AttachJNI(JNIEnv* env,
jclass clazz,
jobject flutterJNI,
jboolean is_background_view) {
fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
auto shell_holder = std::make_unique<AndroidShellHolder>(
FlutterMain::Get().GetSettings(), java_object, is_background_view);
if (shell_holder->IsValid()) {
return reinterpret_cast<jlong>(shell_holder.release());
} else {
return 0;
}
}
這里初始化構(gòu)造函數(shù)AndroidShellHolder
。
2.1.3 AndroidShellHolder
初始化過程中比較重要的代碼如下:
shell\platform\android\android_shell_holder.cc
AndroidShellHolder::AndroidShellHolder(){
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU | ThreadHost::Type::IO};
Shell::CreateCallback<PlatformView> on_create_platform_view = 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
);
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
};
fml::RefPtr<fml::TaskRunner> platform_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
fml::RefPtr<fml::TaskRunner> gpu_runner = thread_host_.gpu_thread->GetTaskRunner();
fml::RefPtr<fml::TaskRunner> ui_runner = thread_host_.ui_thread->GetTaskRunner();
fml::RefPtr<fml::TaskRunner> 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
);
shell_ = Shell::Create(task_runners, // task runners
GetDefaultWindowData(), // window data
settings_, // settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
task_runners.GetGPUTaskRunner()->PostTask([]() {});
task_runners.GetUITaskRunner()->PostTask([]() {)};
}
這個類比較重要项鬼,可以分幾個部分解析:
- 1哑梳、thread_host_是一個ThreadHost結(jié)構(gòu)體的對象,是platform_thread绘盟,ui_thread鸠真,gpu_thread悯仙,io_thread這個四個線程的集合。
進(jìn)一步查看可以發(fā)現(xiàn)Thread類持有一個TaskRunner對象弧哎。
- 2雁比、PlatformViewAndroid,第二步調(diào)用初始化構(gòu)造函數(shù)撤嫩,創(chuàng)建一個on_create_platform_view 對象偎捎,這個類繼承自PlatformView,做平臺View的初始化工作
- 3序攘、四個TaskRunner,看看他的初始化:
Thread初始化
shell\platform\fuchsia\flutter\thread.cc
Thread::Thread(const std::string& name) : joined_(false) {
fml::RefPtr<fml::TaskRunner> runner;
thread_ = std::make_unique<std::thread>([&latch, &runner, name]() -> void {
SetCurrentThreadName(name);
fml::MessageLoop::EnsureInitializedForCurrentThread();
auto& loop = MessageLoop::GetCurrent();
runner = loop.GetTaskRunner();
latch.Signal();
loop.Run();
});
}
在EnsureInitializedForCurrentThread方法中會初始化MessageLoop構(gòu)造函數(shù)茴她,然后獲取一個loop對象,從這個loop對象里獲取TaskRunner程奠。
MessageLoop構(gòu)造函數(shù)
如下:
fml\message_loop.cc
MessageLoop::MessageLoop()
: loop_(MessageLoopImpl::Create()),
task_runner_(fml::MakeRefCounted<fml::TaskRunner>(loop_)) {
}
可見此時初始化了一個MessageLoopImpl構(gòu)造函數(shù)丈牢。
MessageLoopImpl構(gòu)造函數(shù)
fml\message_loop_impl.cc
fml::RefPtr<MessageLoopImpl> MessageLoopImpl::Create() {
#if OS_MACOSX
return fml::MakeRefCounted<MessageLoopDarwin>();
#elif OS_ANDROID
return fml::MakeRefCounted<MessageLoopAndroid>();
#elif OS_FUCHSIA
return fml::MakeRefCounted<MessageLoopFuchsia>();
#elif OS_LINUX
return fml::MakeRefCounted<MessageLoopLinux>();
#elif OS_WIN
return fml::MakeRefCounted<MessageLoopWin>();
#else
return nullptr;
#endif
}
以MessageLoopAndroid為例,MessageLoopAndroid的父類是MessageLoopImpl瞄沙。
MessageLoopImpl構(gòu)造函數(shù)
如下
fml\message_loop_impl.cc
MessageLoopImpl::MessageLoopImpl()
: task_queue_(MessageLoopTaskQueues::GetInstance()),
queue_id_(task_queue_->CreateTaskQueue()),
terminated_(false) {
task_queue_->SetWakeable(queue_id_, this);
}
這里可以看到MessageLoopImpl創(chuàng)建了消息隊列己沛。
fml\platform\android\message_loop_android.cc
MessageLoopAndroid::MessageLoopAndroid(){
int add_result = ::ALooper_addFd(looper_.get(), // looper
timer_fd_.get(), // fd
ALOOPER_POLL_CALLBACK, // ident
kWakeEvents, // events
read_event_fd, // callback
this // baton
);
}
初始化完成之后,有一個loop.run方法,實際上調(diào)用的是對應(yīng)平臺的Run方法:
fml\platform\android\message_loop_android.cc
void MessageLoopAndroid::Run() {
running_ = true;
while (running_) {
int result = ::ALooper_pollOnce(-1, //infinite timeout
nullptr, // out fd,
nullptr, // out events,
nullptr // out data
);
}
}
這里運用了linux的poll機制距境。
可以看到這里循環(huán)等待消息處理申尼。
接下來看看runner = loop.GetTaskRunner()
方法,要探究一下這個TaskRunner是怎么初始化的垫桂。
再回到MessageLoop構(gòu)造函數(shù)师幕,還是之前貼的代碼,可以看到有一行代碼诬滩,構(gòu)造函數(shù)的初始化成員變量霹粥,如下:
fml\message_loop.cc
task_runner_(fml::MakeRefCounted<fml::TaskRunner>(loop_))
這個loop_實際是MessageLoopImpl類型,而GetTaskRunner()方法定義在MessageLoop類中疼鸟,返回的就是task_runner_后控。
可見TaskRunner無非就是持有一個loop對象,并將task提交給MessageLoopImpl執(zhí)行空镜。而從消息隊列中取對象執(zhí)行的時候是在每一個對應(yīng)的線程中忆蚀。
2.1.4 Shell::Create
這個方法也很重要,因為在這里我們可以看到他初始化了Engine姑裂。
直接看比較重要的兩個初始化構(gòu)造函數(shù):
第一個:
std::unique_ptr<Shell> Shell::Create(){
auto vm = DartVMRef::Create(settings);
auto vm_data = vm->GetVMData();
}
在這里啟動Dart虛擬機:
DartVMRef DartVMRef::Create(Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot) {
if (auto vm = gVM.lock()) {
return DartVMRef{std::move(vm)};
}
auto vm = DartVM::Create(std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
isolate_name_server //
);
return DartVMRef{std::move(vm)};
}
如果已經(jīng)存在一個vm的對象就直接返回馋袜,否則創(chuàng)建一個:
std::shared_ptr<DartVM> DartVM::Create(){
auto vm_data = DartVMData::Create(settings, //
std::move(vm_snapshot), //
std::move(isolate_snapshot) //
);
return std::shared_ptr<DartVM>(
new DartVM(std::move(vm_data), std::move(isolate_name_server)));
}
先創(chuàng)建DartVMData類型對象,看看是怎么創(chuàng)建的:
std::shared_ptr<const DartVMData> DartVMData::Create(
Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot) {
if (!vm_snapshot || !vm_snapshot->IsValid()) {
vm_snapshot = DartSnapshot::VMSnapshotFromSettings(settings);
}
if (!isolate_snapshot || !isolate_snapshot->IsValid()) {
isolate_snapshot = DartSnapshot::IsolateSnapshotFromSettings(settings);
}
return std::shared_ptr<const DartVMData>(new DartVMData(
std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot) //
));
}
這里的代碼比較核心舶斧,因為我們在應(yīng)用層寫的dart代碼能夠運行起來欣鳖,主要依靠這兩個對象。一個是跟VM有關(guān)的叫core snapshot茴厉,一個是與isolate有關(guān)的泽台,叫isolate snapshot什荣。
初始化DartVMData工作完成之后,返回他的對象給DartVM怀酷。
自此稻爬,DartVM對象算是建立起來了,并啟動了VM虛擬機蜕依。
第二個:
std::unique_ptr<Shell> Shell::Create(){
fml::AutoResetWaitableEvent latch;
std::unique_ptr<Shell> shell;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetPlatformTaskRunner(),
fml::MakeCopyable([&latch, //
vm = std::move(vm), //
&shell, //
task_runners = std::move(task_runners), //
window_data, //
settings, //
isolate_snapshot = std::move(isolate_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
]() mutable {
shell = CreateShellOnPlatformThread(
std::move(vm),
std::move(task_runners), //
window_data, //
settings, //
std::move(isolate_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
);
latch.Signal();
}));
latch.Wait();
return shell;
}
AutoResetWaitableEvent
其實是一個線程安全的消息同步處理類桅锄。當(dāng)調(diào)用Signal方法時表示解除阻塞,返回數(shù)據(jù)样眠;當(dāng)調(diào)用Wait方法的時候表示阻塞當(dāng)前消息友瘤,等待返回。
這里主要看看CreateShellOnPlatformThread方法:
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(){
auto shell = std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));
auto engine_future = engine_promise.get_future();
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
fml::MakeCopyable([&engine_promise, //
shell = shell.get(), //
&dispatcher_maker, //
&window_data, //
isolate_snapshot = std::move(isolate_snapshot), //
vsync_waiter = std::move(vsync_waiter), //
&weak_io_manager_future, //
&snapshot_delegate_future, //
&unref_queue_future //
]() mutable {
engine_promise.set_value(std::make_unique<Engine>(
*shell, //
dispatcher_maker, //
*shell->GetDartVM(), //
std::move(isolate_snapshot), //
task_runners, //
window_data, //
shell->GetSettings(), //
std::move(animator), //
weak_io_manager_future.get(), //
unref_queue_future.get(), //
snapshot_delegate_future.get() //
));
}));
return shell;
}
到這里可以看到開始對Engine初始化了檐束”柩恚看看Engine類的代碼注釋:
Engine是Shell的一個組件,并通過UI TaskRunner創(chuàng)建被丧。他負(fù)責(zé)管理根isolate的需求任務(wù)以及這些isolate的運行時盟戏。Engine只能在UI TaskRunner里面被創(chuàng)建,調(diào)用甥桂,回收柿究。
flutter應(yīng)用的根isolate獲取窗口的綁定對象,通過這些對象格嘁,根isolate可以調(diào)度幀笛求,提交視圖層級渲染廊移,請求圖片解壓縮糕簿,并將這些圖片提交給GPU等。非根isolate不具備以上的那些能力狡孔,而是活在VM虛擬機管理的線程池中懂诗。
Engine負(fù)責(zé)根isolate的整個生命周期,當(dāng)engine被回收的時候苗膝,他的所有者(Shell)假設(shè)根isolate已經(jīng)關(guān)閉了并且將適合的資源回收殃恒,然而一個Engine只能持有一個根isolate單實例,一旦有請求辱揭,engine可以將這個根isolate重啟离唐。這也是為什么冷啟動開發(fā)場景被支持的原因。
Engine被初始化創(chuàng)建的時候问窃,根isolate就被創(chuàng)建了亥鬓,但是并不直接運行起來,只有等到Engine::Run被調(diào)用的時候域庇,才會運行起來嵌戈。
看看Engine的初始化:
shell\common\engine.cc
Engine::Engine(Delegate& delegate,
const PointerDataDispatcherMaker& dispatcher_maker,
DartVM& vm,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
std::unique_ptr<Animator> animator,
fml::WeakPtr<IOManager> io_manager,
fml::RefPtr<SkiaUnrefQueue> unref_queue,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate){
runtime_controller_ = std::make_unique<RuntimeController>(
*this, // runtime delegate
&vm, // VM
std::move(isolate_snapshot), // isolate snapshot
task_runners_, // task runners
std::move(snapshot_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
window_data, // window data
settings_.isolate_create_callback, // isolate create callback
settings_.isolate_shutdown_callback, // isolate shutdown callback
settings_.persistent_isolate_data // persistent isolate data
);
}
這里RuntimeController被初始化覆积,看看他的構(gòu)造函數(shù):
runtime\runtime_controller.cc
RuntimeController::RuntimeController(){
auto strong_root_isolate = DartIsolate::CreateRootIsolate(
vm_->GetVMData()->GetSettings(), //
isolate_snapshot_, //
task_runners_, //
std::make_unique<Window>(this), //
snapshot_delegate_, //
io_manager_, //
unref_queue_, //
image_decoder_, //
p_advisory_script_uri, //
p_advisory_script_entrypoint, //
nullptr, //
isolate_create_callback_, //
isolate_shutdown_callback_ //
).lock();
}
創(chuàng)建引擎的同時創(chuàng)建根isolate谈秫。
runtime\dart_isolate.cc
std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(){
auto isolate_group_data = std::make_unique<std::shared_ptr<DartIsolateGroupData>>(
std::shared_ptr<DartIsolateGroupData>(new DartIsolateGroupData(
settings, // settings
std::move(isolate_snapshot), // isolate snapshot
advisory_script_uri, // advisory URI
advisory_script_entrypoint, // advisory entrypoint
nullptr, // child isolate preparer
isolate_create_callback, // isolate create callback
isolate_shutdown_callback // isolate shutdown callback
)));
auto isolate_data = std::make_unique<std::shared_ptr<DartIsolate>>(
std::shared_ptr<DartIsolate>(new DartIsolate(
settings, // settings
task_runners, // task runners
std::move(snapshot_delegate), // snapshot delegate
std::move(io_manager), // IO manager
std::move(unref_queue), // Skia unref queue
std::move(image_decoder), // Image Decoder
advisory_script_uri, // advisory URI
advisory_script_entrypoint, // advisory entrypoint
true // is_root_isolate
)));
DartErrorString error;
Dart_Isolate vm_isolate = CreateDartIsolateGroup(
std::move(isolate_group_data),
std::move(isolate_data),
flags,
error.error());
std::shared_ptr<DartIsolate>* root_isolate_data = static_cast<std::shared_ptr<DartIsolate>*>(Dart_IsolateData(vm_isolate));
(*root_isolate_data)->SetWindow(std::move(window));
return (*root_isolate_data)->GetWeakIsolatePtr();
}
這里先為DartIsolateGroup創(chuàng)建組數(shù)據(jù)查辩,然后為DartIsolateGroup創(chuàng)建子DartIsolate没咙。
到這里我們可以看到DartVM鹃觉,Engine于樟,Shell創(chuàng)建先后關(guān)系是:AndroidShellHolder -> Shell -> TaskRunner -> DartVm -> Engine -> RuntimeController -> DartIsolate衬以。
總結(jié)
追溯上述源碼總結(jié)AndroidShellHolder的構(gòu)造函數(shù)便贵,可以發(fā)現(xiàn)最主要的是創(chuàng)建了DartVM嘲碧,Engine偿短,DartIsolate欣孤,Shell四個對象,啟動DartVM虛擬機昔逗,為上層應(yīng)用程序被Launch做準(zhǔn)備降传。
2.2 處理SurfaceHolder.Callback回調(diào)
先看onSurfaceCreated回調(diào),這個函數(shù)最終會調(diào)用到FlutterJNI的nativeSurfaceCreated方法,它被注冊到了shell\platform\android\platform_view_android_jni.cc文件中的SurfaceCreated的方法:
static void SurfaceCreated(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jobject jsurface) {
auto window = fml::MakeRefCounted<AndroidNativeWindow>(ANativeWindow_fromSurface(env, jsurface));
ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyCreated(std::move(window));
}
這里的ANDROID_SHELL_HOLDER就是2.1.3中初始化的AndroidShellHolder對象勾怒,而GetPlatformView()方法獲取的是PlatformViewAndroid類型的對象.
2.2.1 PlatformViewAndroid
看看PlatformViewAndroid的NotifyCreated方法:
void PlatformViewAndroid::NotifyCreated(
fml::RefPtr<AndroidNativeWindow> native_window) {
if (android_surface_) {
InstallFirstFrameCallback();
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetGPUTaskRunner(),
[&latch, surface = android_surface_.get(),
native_window = std::move(native_window)]() {
surface->SetNativeWindow(native_window);
latch.Signal();
});
latch.Wait();
}
PlatformView::NotifyCreated();
}
- InstallFirstFrameCallback
該方法啟動了platform TaskRunner婆排,同時通知java層,第一幀已經(jīng)渲染好了笔链。最終調(diào)用到了shell\platform\android\platform_view_android_jni.cc中的FlutterViewOnFirstFrame方法:
void FlutterViewOnFirstFrame(JNIEnv* env, jobject obj) {
env->CallVoidMethod(obj, g_on_first_frame_method);
FML_CHECK(CheckException(env));
}
g_on_first_frame_method對應(yīng)的其實是java層的onFirstFrame方法段只,其實是在FlutterJNI方法中:
g_on_first_frame_method = env->GetMethodID(g_flutter_jni_class->obj(), "onFirstFrame", "()V");
看看FlutterJNI中的這個方法:
void onFirstFrame() {
for (FlutterUiDisplayListener listener : flutterUiDisplayListeners) {
listener.onFlutterUiDisplayed();
}
}
這個onFlutterUiDisplayed最終回調(diào)給了FlutterNativeView中的flutterUiDisplayListener對象,而他收到消息之后鉴扫,調(diào)用FlutterView的onFirstFrame方法赞枕,這個方法中主要做消息分發(fā),誰監(jiān)聽了FirstFrameListener坪创,就分發(fā)消息給誰炕婶。
其實還是FlutterView自己監(jiān)聽了,只不過是在FlutterActivityDelegate類中完成的莱预,這個實際到第一屏啟動頁的處理柠掂,后面再說。
接下來啟動了gpu TaskRunner依沮。
- PlatformView::NotifyCreated()
看看這個方法:
void PlatformView::NotifyCreated() {
auto* platform_view = this;
fml::ManualResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetGPUTaskRunner(), [platform_view, &surface, &latch]() {
surface = platform_view->CreateRenderingSurface();
latch.Signal();
});
latch.Wait();
delegate_.OnPlatformViewCreated(std::move(surface));
}
這個delegate_其實是Shell涯贞,在AndroidShellHolder的構(gòu)造函數(shù)里面可以得知,看看這個OnPlatformViewCreated方法:
void Shell::OnPlatformViewCreated(std::unique_ptr<Surface> surface) {
auto ui_task = [engine = engine_->GetWeakPtr(), //
gpu_task_runner = task_runners_.GetGPUTaskRunner(), //
gpu_task,
should_post_gpu_task,
&latch //
] {
if (engine) {
engine->OnOutputSurfaceCreated();
}
}
auto io_task = [io_manager = io_manager_->GetWeakPtr(),
platform_view,
ui_task_runner = task_runners_.GetUITaskRunner(),
ui_task
] {
if (io_manager && !io_manager->GetResourceContext()) {
io_manager->NotifyResourceContextAvailabl (platform_view->CreateResourceContext());
}
// Step 1: Next, post a task on the UI thread to tell the engine that it has
// an output surface.
fml::TaskRunner::RunNowOrPostTask(ui_task_runner, ui_task);
};
fml::TaskRunner::RunNowOrPostTask(task_runners_.GetIOTaskRunner(), io_task);
}
這里主要是檢查資源危喉,以及通知engine可以渲染并輸出surface了宋渔。
3、啟動
3.1 啟動flash頁面
FlutterView創(chuàng)建成功之后辜限,就開始對lauch頁做處理了皇拣,就是所說的應(yīng)用啟動開屏第一頁。先看看有沒有定義launchView列粪,在方法createLaunchView中:
private View createLaunchView() {
if (!showSplashScreenUntilFirstFrame()) {
return null;
}
final Drawable launchScreenDrawable = getLaunchScreenDrawableFromActivityTheme();
if (launchScreenDrawable == null) {
return null;
}
final View view = new View(activity);
view.setLayoutParams(matchParent);
view.setBackground(launchScreenDrawable);
return view;
}
showSplashScreenUntilFirstFrame函數(shù)先判斷第一頁的標(biāo)志位是否打開:
private Boolean showSplashScreenUntilFirstFrame() {
try {
ActivityInfo activityInfo = activity.getPackageManager().getActivityInfo(
activity.getComponentName(),
PackageManager.GET_META_DATA|PackageManager.GET_ACTIVITIES);
Bundle metadata = activityInfo.metaData;
return metadata != null && metadata.getBoolean("io.flutter.app.android.SplashScreenUntilFirstFrame");
} catch (NameNotFoundException e) {
return false;
}
}
也就是說看看當(dāng)前的Activity在AndroidManifest.xml里面定義的時候审磁,是否定義了這個key = io.flutter.app.android.SplashScreenUntilFirstFrame的metadata谈飒,并返回他配置的值,默認(rèn)返回false态蒂『即耄基于這個判斷,如果返回true钾恢,就進(jìn)行下一步手素,否則返回空。
看看下一步怎么獲取第一幀的資源:
private Drawable getLaunchScreenDrawableFromActivityTheme() {
TypedValue typedValue = new TypedValue();
if (!activity.getTheme().resolveAttribute(
android.R.attr.windowBackground,
typedValue,
true)) {
return null;
}
if (typedValue.resourceId == 0) {
return null;
}
try {
return activity.getResources().getDrawable(typedValue.resourceId);
} catch (NotFoundException e) {
Log.e(TAG, "Referenced launch screen windowBackground resource does not exist");
return null;
}
}
從這里看到瘩蚪,先判斷我們的Activity在AndroidManifest.xml里面定義的Theme泉懦,從這個theme里面獲取windowBackground標(biāo)簽的值給到typedValue。如果資源id有效疹瘦,就給到Drawable崩哩,返回Drawable對象。
最后把這個Drawable對象設(shè)置成View的背景返回就行了言沐。
lauchView不為空邓嘹,接下來addLaunchView:
private void addLaunchView() {
if (launchView == null) {
return;
}
activity.addContentView(launchView, matchParent);
flutterView.addFirstFrameListener(new FlutterView.FirstFrameListener() {
@Override
public void onFirstFrame() {
FlutterActivityDelegate.this.launchView.animate()
.alpha(0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
((ViewGroup) FlutterActivityDelegate.this.launchView.getParent())
.removeView(FlutterActivityDelegate.this.launchView);
FlutterActivityDelegate.this.launchView = null;
}
});
FlutterActivityDelegate.this.flutterView.removeFirstFrameListener(this);
}
});
activity.setTheme(android.R.style.Theme_Black_NoTitleBar);
}
先將launchView添加到最頂層,然后設(shè)置第一幀的監(jiān)聽险胰,當(dāng)?shù)谝粠秩就戤呏笮谘海蛯aunchView做一個透明度的動畫,動畫執(zhí)行完畢之后起便,將launchView移除棚贾,并移除第一幀的監(jiān)聽。
3.2 啟動dart代碼
加下來就會運行runBundle函數(shù):
/io/flutter/app/FlutterActivityDelegate.java
public void onCreate(Bundle savedInstanceState) {
String appBundlePath = FlutterMain.findAppBundlePath();
if (appBundlePath != null) {
runBundle(appBundlePath);
}
}
private void runBundle(String appBundlePath) {
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
FlutterRunArguments args = new FlutterRunArguments();
args.bundlePath = appBundlePath;
args.entrypoint = "main";
flutterView.runFromBundle(args);
}
}
appBundlePath對應(yīng)的flutter_assets榆综,entrypoint對應(yīng)的入口名稱妙痹,就是main.dart。
看看runFromBundle函數(shù)最終調(diào)用到了哪里:
io\flutter\view\FlutterNativeView.java
public void runFromBundle(FlutterRunArguments args) {
mFlutterJNI.runBundleAndSnapshotFromLibrary(
args.bundlePath,
args.entrypoint,
args.libraryPath,
mContext.getResources().getAssets()
);
applicationIsRunning = true;
}
到這里就通過FlutterJNI調(diào)用到了runBundleAndSnapshotFromLibrary:
io\flutter\embedding\engine\FlutterJNI.java
public void runBundleAndSnapshotFromLibrary(
@NonNull String bundlePath,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager assetManager
) {
nativeRunBundleAndSnapshotFromLibrary(
nativePlatformViewId,
bundlePath,
entrypointFunctionName,
pathToEntrypointFunction,
assetManager
);
}
最終到了native層:
shell\platform\android\platform_view_android_jni.cc
static void RunBundleAndSnapshotFromLibrary(){
RunConfiguration config(std::move(isolate_configuration), std::move(asset_manager));
{
auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
if ((entrypoint.size() > 0) && (libraryUrl.size() > 0)) {
config.SetEntrypointAndLibrary(std::move(entrypoint), std::move(libraryUrl));
} else if (entrypoint.size() > 0) {
config.SetEntrypoint(std::move(entrypoint));
}
}
ANDROID_SHELL_HOLDER->Launch(std::move(config));
}
看看Launch函數(shù):
shell\platform\android\android_shell_holder.cc
void AndroidShellHolder::Launch(RunConfiguration config) {
shell_->RunEngine(std::move(config));
}
最終調(diào)用的地方在Shell.cc里面:
shell\common\shell.cc
void Shell::RunEngine(){
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable(
[run_configuration = std::move(run_configuration),
weak_engine = weak_engine_, result]() mutable {
auto run_result = weak_engine->Run(std::move(run_configuration));
result(run_result);
}));
}
到這里奖年,可以看到要啟動引擎了:
shell\common\engine.cc
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
auto isolate_launch_status = PrepareAndLaunchIsolate(std::move(configuration));
std::shared_ptr<DartIsolate> isolate = runtime_controller_->GetRootIsolate().lock();
bool isolate_running = isolate && isolate->GetPhase() == DartIsolate::Phase::Running;
return isolate_running ? Engine::RunStatus::Success : Engine::RunStatus::Failure;
}
之前有說過根isolate的啟動细诸,是在engine啟動的時候才開始啟動沛贪,現(xiàn)在看看怎么啟動isolate的:
shell\common\engine.cc
Engine::RunStatus Engine::PrepareAndLaunchIsolate(){
std::shared_ptr<DartIsolate> isolate = runtime_controller_->GetRootIsolate().lock();
if (!isolate_configuration->PrepareIsolate(*isolate)) {
return RunStatus::Failure;
}
if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(), configuration.GetEntrypoint(), settings_.dart_entrypoint_args)) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
return RunStatus::Success;
}
先獲取isolate對象陋守,然后運行RunFromLibrary方法:
runtime\dart_isolate.cc
[[nodiscard]] bool DartIsolate::RunFromLibrary(){
auto user_entrypoint_function = Dart_GetField(Dart_LookupLibrary(tonic::ToDart(library_name.c_str())), tonic::ToDart(entrypoint_name.c_str()));
auto entrypoint_args = tonic::ToDart(args);
if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
return false;
}
phase_ = Phase::Running;
if (on_run) {
on_run();
}
return true;
}
Dart_GetField的目的是在我們的dart代碼中目錄lib中查找main.dart文件,然后調(diào)用InvokeMainEntrypoint函數(shù)執(zhí)行里面的main方法:
runtime\dart_isolate.cc
[[nodiscard]] static bool InvokeMainEntrypoint(){
Dart_Handle start_main_isolate_function = tonic::DartInvokeField(Dart_LookupLibrary(tonic::ToDart("dart:isolate")),
"_getStartMainIsolateFunction", {});
if (tonic::LogIfError(tonic::DartInvokeField(
Dart_LookupLibrary(tonic::ToDart("dart:ui")),
"_runMainZoned",{start_main_isolate_function,
user_entrypoint_function,
args}))) {
return false;
}
return true;
}
看看_runMainZoned方法:
lib\ui\hooks.dart
void _runMainZoned(Function startMainIsolateFunction,
Function userMainFunction,
List<String> args) {
startMainIsolateFunction((){
runZonedGuarded<void>(() {
userMainFunction();
}, (Object error, StackTrace stackTrace) {
});
}, null);
}
最終調(diào)用的還是用戶的main函數(shù)利赋,就是我們一開始傳遞過去entrypoint值水评。
4、Isolate
看看DartIsolate這個類的注釋:
他代表了一個活著的isolate示例媚送。一個isolate是一個獨立的Dart可執(zhí)行上下文中燥。不同的isolate不共享內(nèi)存,并能夠被Dart VM虛擬機管理的工作線程池中的某一個Dart VM虛擬機同時調(diào)度塘偎。
Dart VM虛擬機控制著Dart isolate的整個生命周期疗涉,正因為如此拿霉,引擎從來不會在一段很長的時間段內(nèi)持有Dart VM虛擬機的強指針,這樣就允許Dart VM虛擬機或isolate本身去中斷Dart的執(zhí)行但并不影響引擎運行咱扣。
那些引擎創(chuàng)建的isolate看起來像是代表了UI綁定的Flutter應(yīng)用程序代碼被稱作底層(root)isolate绽淘。
根isolate有以下特性:
- 根isolate創(chuàng)建了一個新的isolate組,子isolate被添加到這個組里面闹伪,當(dāng)根isolate死了沪铭,那么組里面所有的子isolate將會被中斷。
- 只有根isolate能夠獲取UI綁定
- 根isolate在引擎管理的線程上執(zhí)行他們的代碼偏瓤,而其他的isolate則在引擎無法控制的被Dart VM虛擬機管理的工作線程池上運行他們的Dart代碼
- 正因為引擎不知道非根isolate運行在哪個線程杀怠,所以引擎也沒有機會去獲取一個非根部isolate的引用,而這些非根isolate只能被他們自己中斷或當(dāng)他們的isolate組被銷毀的時候而中斷厅克。
下面看看native層的調(diào)用流程圖:
再看看Engine,Dart VM,Isolate之間的關(guān)系:
Shell從四個Thread中獲取到了四個Thread對應(yīng)的TaskRunner赔退,而TaskRunner中實際上是MessageLoopImpl在干活,從消息隊列中取出消息處理证舟。
https://github.com/flutter/flutter/wiki/The-Engine-architecture
比較特殊的是离钝,Engine是在UI TaskRunner里面新建并運行,在創(chuàng)建的過程中一并創(chuàng)建了Dart VM和Root Isolate褪储,我們上層寫的dart代碼也是運行在這個TaskRunner里面卵渴。不同的是,當(dāng)傳遞圖片到GPU鲤竹,畫面幀渲染的時候使用的是GPU TaskRunner,而一些IO操作比如從assets里面讀取文件等則是在IO TaskRunner里面去執(zhí)行浪读。IO與GPU交互頻繁,為了性能辛藻,IO TaskRunner 設(shè)置了一個特殊的上下文在一個相同的共享組里面碘橘,并將他作為GPU TaskRunner的主要上下文。
上述這些操作都是通過DartVM調(diào)度Isolate去實現(xiàn)的吱肌,目前Google在Android平臺上TaskRunner的策略是痘拆,一個Engine實例創(chuàng)建一個UI TaskRunner,一個IO TaskRunner氮墨,一個GPU TaskRunner纺蛆,所有的Engine實例共享一個Platform TaskRunner和他的Thread。