在Android中,應用的啟動都是從Application
的建立開始,所以基本上都會來自定義實現Application
並在該類中進行一些初始化操作,如推送、分享、支付等。Flutter
也不例外,也會在自定義的Application
中進行引擎的初始化操作。
1、引擎的初始化
FlutterApplication
就是一個自定義的Application
類,在該類中進行了引擎的初始化,程式碼如下。
public class FlutterApplication extends Application {
@Override
@CallSuper
public void onCreate() {
super.onCreate();
//初始化
FlutterMain.startInitialization(this);
}
...
}
複製程式碼
再來看FlutterMain
類的startInitialization
方法,因為引擎的初始化是通過該方法開始的。
public static void startInitialization(@NonNull Context applicationContext) {
//如果在進行Robolectric測試,則暫不進行初始化操作
if (isRunningInRobolectricTest) {
return;
}
FlutterLoader.getInstance().startInitialization(applicationContext);
}
複製程式碼
在startInitialization
方法中又呼叫了FlutterLoader
的startInitialization
方法,該方法是引擎初始化的具體實現。
public class FlutterLoader {
...
public void startInitialization(@NonNull Context applicationContext) {
startInitialization(applicationContext, new Settings());
}
public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
//不允許多次初始化
if (this.settings != null) {
return;
}
//必須在主執行緒中初始化
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
}
this.settings = settings;
//當前時間
long initStartTimestampMillis = SystemClock.uptimeMillis();
//初始化配置
initConfig(applicationContext);
//初始化資源
initResources(applicationContext);
//載入flutter.so動態庫
System.loadLibrary("flutter");
//初始化一個類VsyncWaiter,主要是同步Android的VSYNC訊號給Engine
VsyncWaiter
.getInstance((WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE))
.init();
//記錄Engine的初始化時間
long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
FlutterJNI.nativeRecordStartTimestamp(initTimeMillis);
}
...
}
複製程式碼
這裡重點在於flutter.so
動態庫的載入。由於Java VM在載入動態庫時第一個呼叫的是JNI_OnLoad
函式,所以就先來看該函式的實現。
[-> flutter/shell/platform/android/library_loader.cc]
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
//Initialize the Java VM.
//將vm作為一個全域性變數
fml::jni::InitJavaVM(vm);
//獲取當前執行緒的env
JNIEnv* env = fml::jni::AttachCurrentThread();
bool result = false;
//Register FlutterMain.
//Java Native方法的註冊,主要是註冊了FlutterJNI類的nativeInit、nativeRecordStartTimestamp方法。
result = flutter::FlutterMain::Register(env);
//Register PlatformView
//Java Native方法的註冊
result = flutter::PlatformViewAndroid::Register(env);
//Register VSyncWaiter.
//Java Native方法的註冊
result = flutter::VsyncWaiterAndroid::Register(env);
return JNI_VERSION_1_4;
}
複製程式碼
到此,引擎就已經成功初始化,流程圖如下。
2、Engine物件的建立
引擎初始化成功後,就可以來建立引擎。在Android
中,引擎是從FlutterActivity
的onCreate
方法開始建立的,程式碼如下。
public class FlutterActivity extends Activity implements FlutterView.Provider, PluginRegistry, ViewFactory {
private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
private final FlutterActivityEvents eventDelegate = delegate;
private final FlutterView.Provider viewProvider = delegate;
private final PluginRegistry pluginRegistry = delegate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
eventDelegate.onCreate(savedInstanceState);
}
}
複製程式碼
顧名思義,FlutterActivityDelegate
是一個代理類,全權負責FlutterActivity
的所有工作。由於Activity
在其生命週期內呼叫的第一個方法是onCreate
。所以來看類FlutterActivityDelegate
中的onCreate
方法的具體實現。
public final class FlutterActivityDelegate
implements FlutterActivityEvents,
FlutterView.Provider,
PluginRegistry {
@Override
public void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(0x40000000);
window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI);
}
String[] args = getArgsFromIntent(activity.getIntent());
FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), args);
//是否自定義FlutterView,預設不需要自定義
flutterView = viewFactory.createFlutterView(activity);
if (flutterView == null) {
//是否自定義FlutterNativeView,預設不自定義
FlutterNativeView nativeView = viewFactory.createFlutterNativeView();
//建立flutterView
flutterView = new FlutterView(activity, null, nativeView);
//flutterView鋪滿整個螢幕
flutterView.setLayoutParams(matchParent);
activity.setContentView(flutterView);
//建立launchView,launchView是Flutter載入第一幀前的展示View
launchView = createLaunchView();
if (launchView != null) {
addLaunchView();
}
}
if (loadIntent(activity.getIntent())) {
return;
}
//獲取flutter程式碼路徑
String appBundlePath = FlutterMain.findAppBundlePath();
if (appBundlePath != null) {
//執行Flutter程式碼
runBundle(appBundlePath);
}
}
}
複製程式碼
在onCreate
方法中,主要做了以下兩件事。
- 建立了一個
FlutterView
,該View是Flutter介面在Android端的載體。 - Flutter程式碼的執行,其實現原理後面再詳解。
先來看FlutterView
的建立,它繼承自SurfaceView
,程式碼如下。
public class FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry {
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
super(context, attrs);
Activity activity = getActivity(getContext());
if (activity == null) {
throw new IllegalArgumentException("Bad context");
}
if (nativeView == null) {
//建立FlutterNativeView物件
mNativeView = new FlutterNativeView(activity.getApplicationContext());
} else {
mNativeView = nativeView;
}
...
}
}
複製程式碼
在FlutterView
中,會建立一個FlutterNativeView
物件,其建構函式的實現如下。
public class FlutterNativeView implements BinaryMessenger {
public FlutterNativeView(@NonNull Context context) {
this(context, false);
}
public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
mContext = context;
//建立FlutterPluginRegistry物件
mPluginRegistry = new FlutterPluginRegistry(this, context);
//建立FlutterJNI物件
mFlutterJNI = new FlutterJNI();
mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
//建立DartExecutor物件,該物件主要用於Android與Flutter間的通訊,如生命週期。
this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets());
//新增Engine生命週期監聽
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
//執行attach方法
attach(this, isBackgroundView);
assertAttached();
}
private void attach(FlutterNativeView view, boolean isBackgroundView) {
mFlutterJNI.attachToNative(isBackgroundView);
dartExecutor.onAttachedToJNI();
}
}
//主要是用於Android與Native間的相互呼叫
public class FlutterJNI {
@UiThread
public void attachToNative(boolean isBackgroundView) {
...
nativePlatformViewId = nativeAttach(this, isBackgroundView);
}
//native方法
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
}
複製程式碼
這裡重點在於attach
方法,該方法會通過FlutterJNI
的nativeAttach
方法來進行UI、GPU、IO等執行緒的建立、Dart VM的建立及Engine
物件的建立等。下面先來看nativeAttach
方法在引擎中的對應實現。
[-> flutter/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);
//AndroidShellHolder物件的建立
auto shell_holder = std::make_unique<AndroidShellHolder>(
FlutterMain::Get().GetSettings(), java_object, is_background_view);
...
}
複製程式碼
在AttachJNI
函式中主要是建立一個AndroidShellHolder
物件,它的建構函式實現如下。
[-> flutter/shell/platform/android/android_shell_holder.cc]
AndroidShellHolder::AndroidShellHolder(
flutter::Settings settings,
fml::jni::JavaObjectWeakGlobalRef java_object,
bool is_background_view)
: settings_(std::move(settings)), java_object_(java_object) {
static size_t shell_count = 1;
auto thread_label = std::to_string(shell_count++);
//建立目標執行緒
if (is_background_view) {
//僅建立UI執行緒
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 GPU threads exit.
auto jni_exit_task([key = thread_destruct_key_]() {
FML_CHECK(pthread_setspecific(key, reinterpret_cast<void*>(1)) == 0);
});
thread_host_.ui_thread->GetTaskRunner()->PostTask(jni_exit_task);
if (!is_background_view) {
thread_host_.gpu_thread->GetTaskRunner()->PostTask(jni_exit_task);
}
fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
Shell::CreateCallback<PlatformView> on_create_platform_view =
[is_background_view, java_object, &weak_platform_view](Shell& shell) {
std::unique_ptr<PlatformViewAndroid> platform_view_android;
//建立PlatformViewAndroid物件
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;
};
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
//建立刪格化器
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
};
//將當前執行緒(Android主執行緒)作為平臺執行緒(platform thread)並確保已經初始化Message Loop
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();
}
//建立TaskRunners物件
flutter::TaskRunners task_runners(thread_label, // label
platform_runner, // platform
gpu_runner, // gpu
ui_runner, // ui
io_runner // io
);
//建立Shell物件
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
);
platform_view_ = weak_platform_view;
FML_DCHECK(platform_view_);
is_valid_ = shell_ != nullptr;
if (is_valid_) {
//降低GPU執行緒的優先順序
task_runners.GetGPUTaskRunner()->PostTask([]() {
//Android將-8描述為“最重要的顯示執行緒,用於合成螢幕和檢索輸入事件”。 保守地將GPU執行緒設定為比其優先順序稍低的優先順序。
//將GPU執行緒優先順序設為-5。
if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
//如果無法將GPU執行緒優先順序設為-5,那麼繼續將GPU執行緒優先順序設為-2。
if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
FML_LOG(ERROR) << "Failed to set GPU task runner priority";
}
}
});
//將UI執行緒優先順序設為-1。
task_runners.GetUITaskRunner()->PostTask([]() {
if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
FML_LOG(ERROR) << "Failed to set UI task runner priority";
}
});
}
}
複製程式碼
上面程式碼還是比較多的,但主要做了以下幾件事。
- 目標執行緒的建立,如果
is_background_view
為true,則僅會建立UI執行緒,否則會建立UI、GPU及IO執行緒。is_background_view
預設為false。 - 將當前執行緒(Android主執行緒)作為平臺執行緒(platform thread)並確保已經初始化Message Loop。
Shell
物件的建立。- GPU執行緒及UI執行緒優先順序的修改。
從上面可以得出Android主執行緒(UI執行緒)是作為Flutter
的平臺執行緒(platform thread)存在的,與Flutter
的UI執行緒不是同一執行緒,所以不要將Android的主執行緒(UI執行緒)與Flutter
的UI執行緒搞混。
再來看Shell
物件的建立。
[-> flutter/shell/common/shell.cc]
std::unique_ptr<Shell> Shell::Create(
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
PerformInitializationTasks(settings);
PersistentCache::SetCacheSkSL(settings.cache_sksl);
//Dart虛擬機器的建立
auto vm = DartVMRef::Create(settings);
auto vm_data = vm->GetVMData();
return Shell::Create(std::move(task_runners), //
std::move(window_data), //
std::move(settings), //
vm_data->GetIsolateSnapshot(), // isolate snapshot
on_create_platform_view, //
on_create_rasterizer, //
std::move(vm) //
);
}
複製程式碼
在Create
函式中,會進行Dart VM的建立,由於Dart VM的建立過程比較複雜,這裡就不過多敘述,後面再一一講解。
再來看Create
函式,在該函式中會呼叫CreateShellOnPlatformThread
函式,顧名思義,CreateShellOnPlatformThread
函式就是在平臺執行緒中建立Shell
物件。
[-> flutter/shell/common/shell.cc]
std::unique_ptr<Shell> Shell::Create(
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
DartVMRef vm) {
...
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物件
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;
}
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
DartVMRef vm,
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) {
...
//建立Shell物件
auto shell =
std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));
//在GPU執行緒上建立光柵化器。
std::promise<std::unique_ptr<Rasterizer>> rasterizer_promise;
auto rasterizer_future = rasterizer_promise.get_future();
std::promise<fml::WeakPtr<SnapshotDelegate>> snapshot_delegate_promise;
auto snapshot_delegate_future = snapshot_delegate_promise.get_future();
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetGPUTaskRunner(), [&rasterizer_promise, //
&snapshot_delegate_promise,
on_create_rasterizer, //
shell = shell.get() //
]() {
std::unique_ptr<Rasterizer> rasterizer(on_create_rasterizer(*shell));
snapshot_delegate_promise.set_value(rasterizer->GetSnapshotDelegate());
rasterizer_promise.set_value(std::move(rasterizer));
});
//在平臺執行緒(platform thread)也就是Android主執行緒中建立platform view
auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return nullptr;
}
//由platform view建立vsync waiter,
auto vsync_waiter = platform_view->CreateVSyncWaiter();
if (!vsync_waiter) {
return nullptr;
}
//在IO執行緒上建立IO manager。 必須先初始化IO manager,因為它具有其他子系統依賴的狀態。 必須首先引導它,並獲取必要的引用以初始化其他子系統。
std::promise<std::unique_ptr<ShellIOManager>> io_manager_promise;
auto io_manager_future = io_manager_promise.get_future();
std::promise<fml::WeakPtr<ShellIOManager>> weak_io_manager_promise;
auto weak_io_manager_future = weak_io_manager_promise.get_future();
std::promise<fml::RefPtr<SkiaUnrefQueue>> unref_queue_promise;
auto unref_queue_future = unref_queue_promise.get_future();
auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner();
// TODO(gw280): The WeakPtr here asserts that we are derefing it on the
// same thread as it was created on. We are currently on the IO thread
// inside this lambda but we need to deref the PlatformView, which was
// constructed on the platform thread.
//
// https://github.com/flutter/flutter/issues/42948
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() //
]() {
auto io_manager = std::make_unique<ShellIOManager>(
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();
//在Flutter的UI執行緒中建立engine物件
std::promise<std::unique_ptr<Engine>> engine_promise;
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 {
const auto& task_runners = shell->GetTaskRunners();
//在UI執行緒建立animator,這裡主要是為了將平臺的vsync訊號同步給animator
auto animator = std::make_unique<Animator>(*shell, task_runners,
std::move(vsync_waiter));
//Engine物件的建立,此時已經切換到Flutter的UI執行緒
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() //
));
}));
//啟動Shell
if (!shell->Setup(std::move(platform_view), //
engine_future.get(), //
rasterizer_future.get(), //
io_manager_future.get()) //
) {
return nullptr;
}
return shell;
}
複製程式碼
CreateShellOnPlatformThread
函式的實現還是蠻複雜的,但主要還是做了以下幾件事。
- 在平臺執行緒中建立一個
Shell
物件。 - 在GPU執行緒建立刪格化器,
Flutter
在繪製完成後,會將資料給它進行刪格化處理。關於Flutter
的繪製原理可以參考Flutter的繪製流程簡述這篇文章。 - 在平臺執行緒中建立一個
PlatformViewAndroid
物件。如果is_background_view
為true,會建立一個具備渲染能力的PlatformViewAndroid
物件,否則建立的是一個不具備渲染能力且在後臺執行的PlatformViewAndroid
物件。 - 通過
PlatformView
來建立vsync waiter,主要用於VSYNC訊號的同步。 - 在IO執行緒建立IO manager。
- 在Flutter的UI執行緒建立Engine物件。
- 在平臺執行緒啟動
Shell
,呼叫Shell
物件的Setup
函式。
這裡先忽略其他,主要來看Engine
物件的建立。在其建構函式中,會建立一個RuntimeController
物件。
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)
: delegate_(delegate),
settings_(std::move(settings)),
animator_(std::move(animator)),
activity_running_(true),
have_surface_(false),
image_decoder_(task_runners,
vm.GetConcurrentWorkerTaskRunner(),
io_manager),
task_runners_(std::move(task_runners)),
weak_factory_(this) {
//RuntimeController物件的建立
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
);
pointer_data_dispatcher_ = dispatcher_maker(*this);
}
複製程式碼
這裡的RuntimeController
是一個非常重要的物件,在後面很多地方都會用到它。由於篇幅原因,先來看一下從FlutterActivity
到RuntimeController
物件建立的流程圖。
2.1、RootIsolate物件的建立
再來看RuntimeController
物件的建立。
RuntimeController::RuntimeController(
RuntimeDelegate& p_client,
DartVM* p_vm,
fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
TaskRunners p_task_runners,
fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate,
fml::WeakPtr<IOManager> p_io_manager,
fml::RefPtr<SkiaUnrefQueue> p_unref_queue,
fml::WeakPtr<ImageDecoder> p_image_decoder,
std::string p_advisory_script_uri,
std::string p_advisory_script_entrypoint,
const std::function<void(int64_t)>& idle_notification_callback,
const WindowData& p_window_data,
const fml::closure& p_isolate_create_callback,
const fml::closure& p_isolate_shutdown_callback,
std::shared_ptr<const fml::Mapping> p_persistent_isolate_data)
: client_(p_client),
vm_(p_vm),
isolate_snapshot_(std::move(p_isolate_snapshot)),
task_runners_(p_task_runners),
snapshot_delegate_(p_snapshot_delegate),
io_manager_(p_io_manager),
unref_queue_(p_unref_queue),
image_decoder_(p_image_decoder),
advisory_script_uri_(p_advisory_script_uri),
advisory_script_entrypoint_(p_advisory_script_entrypoint),
idle_notification_callback_(idle_notification_callback),
window_data_(std::move(p_window_data)),
isolate_create_callback_(p_isolate_create_callback),
isolate_shutdown_callback_(p_isolate_shutdown_callback),
persistent_isolate_data_(std::move(p_persistent_isolate_data)) {
//建立RootIsolate
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();
...
}
複製程式碼
在建構函式中,會呼叫CreateRootIsolate
函式來建立一個isolate
作為根Isolate
。
std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
const Settings& settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::RefPtr<SkiaUnrefQueue> unref_queue,
fml::WeakPtr<ImageDecoder> image_decoder,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
Dart_IsolateFlags* flags,
const fml::closure& isolate_create_callback,
const fml::closure& isolate_shutdown_callback) {
...
//建立isolate物件
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();
}
複製程式碼
再來看CreateDartIsolateGroup
函式,該函式主要做了兩件事。
- 通過Dart VM來建立isolate物件,並將該isolate物件作為root isolate。
- 初始化isolate物件。
Dart_Isolate DartIsolate::CreateDartIsolateGroup(
std::unique_ptr<std::shared_ptr<DartIsolateGroupData>> isolate_group_data,
std::unique_ptr<std::shared_ptr<DartIsolate>> isolate_data,
Dart_IsolateFlags* flags,
char** error) {
//通過Dart VM建立一個isolate物件
Dart_Isolate isolate = Dart_CreateIsolateGroup(
(*isolate_group_data)->GetAdvisoryScriptURI().c_str(),
(*isolate_group_data)->GetAdvisoryScriptEntrypoint().c_str(),
(*isolate_group_data)->GetIsolateSnapshot()->GetDataMapping(),
(*isolate_group_data)->GetIsolateSnapshot()->GetInstructionsMapping(),
flags, isolate_group_data.get(), isolate_data.get(), error);
if (isolate == nullptr) {
return nullptr;
}
// Ownership of the isolate data objects has been transferred to the Dart VM.
std::shared_ptr<DartIsolate> embedder_isolate(*isolate_data);
isolate_group_data.release();
isolate_data.release();
//初始化isolate物件
if (!InitializeIsolate(std::move(embedder_isolate), isolate, error)) {
return nullptr;
}
return isolate;
}
複製程式碼
先來看Dart_CreateIsolateGroup
函式在Dart VM的實現,在其實現函式中會建立isolate
物件。
Dart_CreateIsolateGroup(const char* script_uri,
const char* name,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
Dart_IsolateFlags* flags,
void* isolate_group_data,
void* isolate_data,
char** error) {
Dart_IsolateFlags api_flags;
if (flags == nullptr) {
Isolate::FlagsInitialize(&api_flags);
flags = &api_flags;
}
const char* non_null_name = name == nullptr ? "isolate" : name;
std::unique_ptr<IsolateGroupSource> source(
new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
snapshot_instructions, nullptr, -1, *flags));
auto group = new IsolateGroup(std::move(source), isolate_group_data);
IsolateGroup::RegisterIsolateGroup(group);
Dart_Isolate isolate =
CreateIsolate(group, non_null_name, isolate_data, error);
if (isolate != nullptr) {
group->set_initial_spawn_successful();
}
return isolate;
}
複製程式碼
CreateIsolate
函式就會建立一個isolate
物件,關於後續的isolate
物件的建立及isolate
的更多內容可以去閱讀深入理解Isolate這篇文章。
再來看isolate
物件的初始化函式——InitializeIsolate
的實現。
bool DartIsolate::InitializeIsolate(
std::shared_ptr<DartIsolate> embedder_isolate,
Dart_Isolate isolate,
char** error) {
if (!embedder_isolate->Initialize(isolate)) {//初始化
*error = fml::strdup("Embedder could not initialize the Dart isolate.");
9999 return false;
}
//isolate載入library
if (!embedder_isolate->LoadLibraries()) {
*error = fml::strdup(
"Embedder could not load libraries in the new Dart isolate.");
return false;
}
// Root isolates will be setup by the engine and the service isolate (which is
// also a root isolate) by the utility routines in the VM. However, secondary
// isolates will be run by the VM if they are marked as runnable.
if (!embedder_isolate->IsRootIsolate()) {
auto child_isolate_preparer =
embedder_isolate->GetIsolateGroupData().GetChildIsolatePreparer();
if (!child_isolate_preparer(embedder_isolate.get())) {
*error = fml::strdup("Could not prepare the child isolate to run.");
return false;
}
}
return true;
}
//初始化
bool DartIsolate::Initialize(Dart_Isolate dart_isolate) {
if (phase_ != Phase::Uninitialized) {
return false;
}
if (dart_isolate == nullptr) {
return false;
}
if (Dart_CurrentIsolate() != dart_isolate) {
return false;
}
//從這裡開始,可以安全的使用isolate
SetIsolate(dart_isolate);
// We are entering a new scope (for the first time since initialization) and
// we want to restore the current scope to null when we exit out of this
// method. This balances the implicit Dart_EnterIsolate call made by
// Dart_CreateIsolateGroup (which calls the Initialize).
Dart_ExitIsolate();
tonic::DartIsolateScope scope(isolate());
//設定UI執行緒的訊息處理器
SetMessageHandlingTaskRunner(GetTaskRunners().GetUITaskRunner());
if (tonic::LogIfError(
Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))) {
return false;
}
if (!UpdateThreadPoolNames()) {
return false;
}
//初始化完成
phase_ = Phase::Initialized;
return true;
}
void DartIsolate::SetMessageHandlingTaskRunner(
fml::RefPtr<fml::TaskRunner> runner) {
if (!IsRootIsolate() || !runner) {
return;
}
message_handling_task_runner_ = runner;
//設定訊息處理器
message_handler().Initialize(
[runner](std::function<void()> task) { runner->PostTask(task); });
}
複製程式碼
最終在SetMessageHandlingTaskRunner
函式中將UITaskRunner
設定為Flutter
中UI執行緒的訊息處理器,進行UI執行緒中訊息的分發並處理。也就是說在RootIsolate
中,訊息並不是通過執行緒池中來分發及處理的,所以不要在UI執行緒的訊息中進行耗時操作,否則影響UI繪製。其實在Android平臺上的Flutter
的訊息處理機制與Android
中的訊息機制類似,都是使用的Android平臺的Looper
。更多內容後面再來一一講解。
void DartMessageHandler::Initialize(TaskDispatcher dispatcher) {
// Only can be called once.
TONIC_CHECK(!task_dispatcher_ && dispatcher);
task_dispatcher_ = dispatcher;
Dart_SetMessageNotifyCallback(MessageNotifyCallback);
}
複製程式碼
在Dart_SetMessageNotifyCallback
中其實就是給RootIsolate
設定訊息通知回撥,程式碼如下。
DART_EXPORT void Dart_SetMessageNotifyCallback(
Dart_MessageNotifyCallback message_notify_callback) {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
{
NoSafepointScope no_safepoint_scope;
isolate->set_message_notify_callback(message_notify_callback);
}
if (message_notify_callback != nullptr && isolate->HasPendingMessages()) {
::Dart_ExitIsolate();
// If a new handler gets installed and there are pending messages in the
// queue (e.g. OOB messages for doing vm service work) we need to notify
// the newly registered callback, otherwise the embedder might never get
// notified about the pending messages.
message_notify_callback(Api::CastIsolate(isolate));
::Dart_EnterIsolate(Api::CastIsolate(isolate));
}
}
複製程式碼
關於RootIsolate
的相關呼叫流程圖如下。
Engine
物件就已經建立完畢。再回到Shell
中,來看Shell
的Setup
函式是如何啟動的。程式碼如下。
bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
std::unique_ptr<Engine> engine,
std::unique_ptr<Rasterizer> rasterizer,
std::unique_ptr<ShellIOManager> io_manager) {
if (is_setup_) {
return false;
}
//platform_view、engine、rasterizer及io_manager只要有一個建立失敗,Shell啟動就會失敗
if (!platform_view || !engine || !rasterizer || !io_manager) {
return false;
}
platform_view_ = std::move(platform_view);
engine_ = std::move(engine);
rasterizer_ = std::move(rasterizer);
io_manager_ = std::move(io_manager);
// The weak ptr must be generated in the platform thread which owns the unique
// ptr.
weak_engine_ = engine_->GetWeakPtr();
weak_rasterizer_ = rasterizer_->GetWeakPtr();
weak_platform_view_ = platform_view_->GetWeakPtr();
is_setup_ = true;
vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription());
PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
task_runners_.GetIOTaskRunner());
PersistentCache::GetCacheForProcess()->SetIsDumpingSkp(
settings_.dump_skp_on_shader_compilation);
// TODO(gw280): The WeakPtr here asserts that we are derefing it on the
// same thread as it was created on. Shell is constructed on the platform
// thread but we need to call into the Engine on the UI thread, so we need
// to use getUnsafe() here to avoid failing the assertion.
//
// https://github.com/flutter/flutter/issues/42947
display_refresh_rate_ = weak_engine_.getUnsafe()->GetDisplayRefreshRate();
return true;
}
複製程式碼
在Setup
函式中主要是檢查Shell
的子元件是否已經初始化,如Engine
、platform_view
、rasterizer
、io manager
等,然後將這些元件設定為全域性。
如果該函式返回true
就表示引擎已經建立成功。
3、Engine的執行
再回到類FlutterActivityDelegate
中,當引擎建立完畢後,再呼叫runBundle
方法來執行Flutter
程式碼。
public final class FlutterActivityDelegate
implements FlutterActivityEvents,
FlutterView.Provider,
PluginRegistry {
private void runBundle(String appBundlePath) {
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
FlutterRunArguments args = new FlutterRunArguments();
//flutter程式碼路徑
args.bundlePath = appBundlePath;
//flutter入口函式
args.entrypoint = "main";
flutterView.runFromBundle(args);
}
}
}
複製程式碼
先來看FlutterRunArguments
,它僅有三個欄位,如下。
public class FlutterRunArguments {
public String bundlePath;
public String entrypoint;
public String libraryPath;
}
複製程式碼
在runBundle
方法中呼叫FlutterView
的runFromBundle
方法時,欄位libraryPath
為空。在後面會用到根據entrypoint
及libraryPath
有不同實現。
public class FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry {
public void runFromBundle(FlutterRunArguments args) {
assertAttached();
preRun();
//執行flutter程式碼
mNativeView.runFromBundle(args);
postRun();
}
}
public class FlutterNativeView implements BinaryMessenger {
public void runFromBundle(FlutterRunArguments args) {
if (args.entrypoint == null) {
throw new AssertionError("An entrypoint must be specified");
}
assertAttached();
if (applicationIsRunning)
throw new AssertionError(
"This Flutter engine instance is already running an application");
mFlutterJNI.runBundleAndSnapshotFromLibrary(
args.bundlePath,
args.entrypoint,
args.libraryPath,
mContext.getResources().getAssets()
);
applicationIsRunning = true;
}
}
public class FlutterJNI {
@UiThread
public void runBundleAndSnapshotFromLibrary(
@NonNull String bundlePath,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager assetManager
) {
ensureRunningOnMainThread();
ensureAttachedToNative();
nativeRunBundleAndSnapshotFromLibrary(
nativePlatformViewId,
bundlePath,
entrypointFunctionName,
pathToEntrypointFunction,
assetManager
);
}
private native void nativeRunBundleAndSnapshotFromLibrary(
long nativePlatformViewId,
@NonNull String bundlePath,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager manager
);
}
複製程式碼
nativeRunBundleAndSnapshotFromLibrary
又是一個native
方法,它在引擎中對應的函式實現如下。
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jstring jBundlePath,
jstring jEntrypoint,
jstring jLibraryUrl,
jobject jAssetManager) {
...
//根據配置檔案來啟動引擎
ANDROID_SHELL_HOLDER->Launch(std::move(config));
}
複製程式碼
RunBundleAndSnapshotFromLibrary
主要是對傳遞的引數進行封裝,然後呼叫Shell
的Launch
函式來執行引擎。
void AndroidShellHolder::Launch(RunConfiguration config) {
if (!IsValid()) {
return;
}
//根據配置執行引擎
shell_->RunEngine(std::move(config));
}
複製程式碼
RunEngine
函式的程式碼實現如下。
void Shell::RunEngine(RunConfiguration run_configuration) {
RunEngine(std::move(run_configuration), nullptr);
}
void Shell::RunEngine(
RunConfiguration run_configuration,
const std::function<void(Engine::RunStatus)>& result_callback) {
auto result = [platform_runner = task_runners_.GetPlatformTaskRunner(),
result_callback](Engine::RunStatus run_result) {
if (!result_callback) {
return;
}
platform_runner->PostTask(
[result_callback, run_result]() { result_callback(run_result); });
};
//在Flutter的UI執行緒呼叫Engine物件的run函式
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable(
[run_configuration = std::move(run_configuration),
weak_engine = weak_engine_, result]() mutable {
if (!weak_engine) {
result(Engine::RunStatus::Failure);
return;
}
//weak_engine是在執行shell的Setup函式時設定的。
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
物件的Run
函式,就可以讓Engine
物件跑起來,實現程式碼如下。
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
if (!configuration.IsValid()) {
return RunStatus::Failure;
}
last_entry_point_ = configuration.GetEntrypoint();
last_entry_point_library_ = configuration.GetEntrypointLibrary();
//準備並啟動Isolate
auto isolate_launch_status =
PrepareAndLaunchIsolate(std::move(configuration));
...
return isolate_running ? Engine::RunStatus::Success
: Engine::RunStatus::Failure;
}
複製程式碼
下面再來看PrepareAndLaunchIsolate
函式的實現。
Engine::RunStatus Engine::PrepareAndLaunchIsolate(
RunConfiguration configuration) {
...
//預設情況下,configuration.GetEntrypointLibrary()為空
if (configuration.GetEntrypointLibrary().empty()) {
//執行isolate
if (!isolate->Run(configuration.GetEntrypoint(),
settings_.dart_entrypoint_args)) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
} else {
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;
}
複製程式碼
預設情況下,configuration.GetEntrypointLibrary()
返回值為空,所以這裡會呼叫DartIsolate
的run
函式來執行isolate
。
bool DartIsolate::Run(const std::string& entrypoint_name,
const std::vector<std::string>& args,
const fml::closure& on_run) {
if (phase_ != Phase::Ready) {
return false;
}
tonic::DartState::Scope scope(this);
auto user_entrypoint_function =
Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));
auto entrypoint_args = tonic::ToDart(args);
//呼叫main方法
if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
return false;
}
phase_ = Phase::Running;
if (on_run) {
on_run();
}
return true;
}
複製程式碼
InvokeMainEntrypoint
顧名思義就是呼叫Flutter
專案中的入口函式——main
方法。
static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function,
Dart_Handle args) {
if (tonic::LogIfError(user_entrypoint_function)) {
FML_LOG(ERROR) << "Could not resolve main entrypoint function.";
return false;
}
Dart_Handle start_main_isolate_function =
tonic::DartInvokeField(Dart_LookupLibrary(tonic::ToDart("dart:isolate")),
"_getStartMainIsolateFunction", {});
if (tonic::LogIfError(start_main_isolate_function)) {
FML_LOG(ERROR) << "Could not resolve main entrypoint trampoline.";
return false;
}
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;
}
複製程式碼
來看_getStartMainIsolateFunction
函式的實現,它返回了一個_startMainIsolate
函式。
@pragma("vm:entry-point", "call")
Function _getStartMainIsolateFunction() {
return _startMainIsolate;
}
@pragma("vm:entry-point", "call")
void _startMainIsolate(Function entryPoint, List<String> args) {
_startIsolate(
null, // no parent port
entryPoint,
args,
null, // no message
true, // isSpawnUri
null, // no control port
null); // no capabilities
}
複製程式碼
再來看_runMainZoned
函式的實現,它就直接執行_getStartMainIsolateFunction
函式的返回函式_startMainIsolate
。
@pragma('vm:entry-point')
// ignore: unused_element
void _runMainZoned(Function startMainIsolateFunction,
Function userMainFunction,
List<String> args) {
startMainIsolateFunction((){
runZoned<void>(() {
if (userMainFunction is _BinaryFunction) {
// This seems to be undocumented but supported by the command line VM.
// Let's do the same in case old entry-points are ported to Flutter.
(userMainFunction as dynamic)(args, '');
} else if (userMainFunction is _UnaryFunction) {
(userMainFunction as dynamic)(args);
} else {
userMainFunction();
}
}, onError: (Object error, StackTrace stackTrace) {
_reportUnhandledException(error.toString(), stackTrace.toString());
});
}, null);
}
複製程式碼
在_startMainIsolate
函式中就是直接執行RootIsolate
並執行入口函式。
@pragma("vm:entry-point", "call")
void _startIsolate(
SendPort parentPort,
Function entryPoint,
List<String> args,
var message,
bool isSpawnUri,
RawReceivePort controlPort,
List capabilities) {
...
//將所有使用者程式碼處理延遲到訊息迴圈的下一次執行。 這使我們能夠攔截事件分發中的某些條件,例如從暫停狀態開始。
RawReceivePort port = new RawReceivePort();
port.handler = (_) {
port.close();
if (isSpawnUri) {
if (entryPoint is _BinaryFunction) {
(entryPoint as dynamic)(args, message);
} else if (entryPoint is _UnaryFunction) {
(entryPoint as dynamic)(args);
} else {
entryPoint();
}
} else {
entryPoint(message);
}
};
//確保訊息處理程式已觸發。
port.sendPort.send(null);
}
複製程式碼
在_startIsolate
方法中,就會執行Flutter
中的入口函式,如下。
void main() => runApp(MyApp());
複製程式碼
執行Flutter
程式碼的流程圖如下。
4、總結
由於東西比較多,所以本文只是描述了引擎的整體建立流程,一些細節也沒有具體講述。但如果熟悉了引擎的建立流程,那麼也就能很快的去了解細節的具體實現。
【參考資料】