今天主要帶你們一塊兒分析下flutter是如何啓動、初始化和加載dart代碼的。這裏有幾點須要提早告知:java
因爲篇幅的問題,關於flutter界面建立、繪製過程將略過;android
因爲相關的c++代碼比較多,並且較爲複雜,建議先下載flutter engine的完整開發環境代碼,閱讀本文更方便;c++
本文只分析啓動過程,參考的項目是基於android studio建立的一個默認flutter項目,如下簡稱demo。shell
熟悉android的朋友都知道,一個APP啓動會先執行Application再執行Activity(AndroidManifest.xml中配置的啓動Activity),結合這個,咱們先看看Application裏作了什麼,在分析過程當中咱們將挑取一些關鍵的native方法做爲c++層入口方法做進一步的分析。api
// io.flutter.app.FlutterApplication
public class FlutterApplication extends Application {
@Override
@CallSuper
public void onCreate() {
super.onCreate();
FlutterMain.startInitialization(this);
}
//這塊代碼和FlutterActivityDelegate的生命週期方法結合使用
private Activity mCurrentActivity = null;
public Activity getCurrentActivity() {
return mCurrentActivity;
}
public void setCurrentActivity(Activity mCurrentActivity) {
this.mCurrentActivity = mCurrentActivity;
}
}
// io.flutter.view.FlutterMain中的方法
public static void startInitialization(Context applicationContext, FlutterMain.Settings settings) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
} else if (sSettings == null) {
sSettings = settings;
long initStartTimestampMillis = SystemClock.uptimeMillis();
initConfig(applicationContext);
initAot(applicationContext);
initResources(applicationContext);
System.loadLibrary("flutter");
...
}
}
複製代碼
startInitialization
只能執行在主線程中,不然會拋出異常。經過sSettings
這個變量能夠看出,啓動的過程當中,這個方法將只執行一遍。initConfig
初始化一些變量的配置信息(在AndroidManifest.xml中能夠經過meta-data方式配置這些變量值), System.loadLibrary("flutter")
則完成裝載flutter庫文件,期間會在c++層完成JNI方法的動態註冊。initResources
方法咱們往下看。緩存
private static void initResources(Context applicationContext) {
Context context = applicationContext;
new ResourceCleaner(context).start();
...
sResourceExtractor = new ResourceExtractor(context);
...
sResourceExtractor.start();
}
複製代碼
ResourceCleaner
將清理帶有指定標識的緩存文件,ResourceExtractor
將完成asset 目錄下flutter相關資源的拷貝,這些資源會在後續flutter engine和DartVM等初始化時使用。 而後咱們再來看看啓動activity都作了些什麼app
//MainActivity.java
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
//FlutterActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.eventDelegate.onCreate(savedInstanceState);
}
複製代碼
先看FlutterActivity中執行onCreate,能夠看到這裏面並無當前ContentView的設置,那麼其內容界面是在哪裏設置的呢,咱們能夠看到第二句this.eventDelegate.onCreate(savedInstanceState);
,最終咱們發現Activity中顯示的view是在代理類中進行初始化的,下面看下代理類FlutterActivityDelegate
的執行,ide
//FlutterActivityDelegate.java
public void onCreate(Bundle savedInstanceState) {
...
String[] args = getArgsFromIntent(this.activity.getIntent());
FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
this.flutterView = this.viewFactory.createFlutterView(this.activity);
if (this.flutterView == null) {
FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
this.flutterView.setLayoutParams(matchParent);
this.activity.setContentView(this.flutterView);
this.launchView = this.createLaunchView();
if (this.launchView != null) {
this.addLaunchView();
}
}
...
this.runBundle(appBundlePath);
...
}
複製代碼
在這裏咱們須要注意FlutterMain.ensureInitializationComplete的執行,函數
//FlutterMain.java
public static void ensureInitializationComplete(Context applicationContext, String[] args) {
...
sResourceExtractor.waitForCompletion();
...
nativeInit(applicationContext, (String[])shellArgs.toArray(new String[0]), appBundlePath, appStoragePath, engineCachesPath);
sInitialized = true;
...
}
//c++關鍵方法1
private static native void nativeInit(Context var0, String[] var1, String var2, String var3, String var4);
複製代碼
它將等待解壓任務結束,資源處理完畢,而後拼接參數,完成參數初始化後將執行nativeInit
方法對c++層初始化。oop
而後會建立FlutterView對象,這裏面還包含了不少關鍵對象的建立,這個下文將會分析到。
//FlutterView.java的構造方法
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
super(context, attrs);
...
if (nativeView == null) {
this.mNativeView = new FlutterNativeView(activity.getApplicationContext());
} else {
this.mNativeView = nativeView;
}
this.mNativeView.getFlutterJNI();
this.mIsSoftwareRenderingEnabled = FlutterJNI.nativeGetIsSoftwareRenderingEnabled();
...
this.mNativeView.attachViewAndActivity(this, activity);
this.mSurfaceCallback = new Callback() {
public void surfaceCreated(SurfaceHolder holder) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface());
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceChanged(width, height);
}
public void surfaceDestroyed(SurfaceHolder holder) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceDestroyed();
}
};
this.getHolder().addCallback(this.mSurfaceCallback);
this.mAccessibilityManager = (AccessibilityManager)this.getContext().getSystemService("accessibility");
...
this.mFlutterLocalizationChannel = new MethodChannel(this, "flutter/localization", JSONMethodCodec.INSTANCE);
...
}
複製代碼
這個方法中先執行FlutterNativeView對象建立,而後是FlutterJNI對象建立,再經過c++層完成二者的綁定關係。另外activity和flutterView的綁定關係也在這裏完成,並會在PlatformViewsController中完成註冊方法回調關係。這個方法還包含了界面繪製監聽,flutter繪製的關鍵調用,創建了通信體系(各種Channel)。在c++層會用到的資源處理對象也是從這裏建立的。
//FlutterNativeView.java構造方法
public FlutterNativeView(Context context, boolean isBackgroundView) {
this.mPluginRegistry = new FlutterPluginRegistry(this, context);
this.mFlutterJNI = new FlutterJNI();
this.mFlutterJNI.setRenderSurface(new FlutterNativeView.RenderSurfaceImpl());
this.mFlutterJNI.setPlatformMessageHandler(new FlutterNativeView.PlatformMessageHandlerImpl());
this.mFlutterJNI.addEngineLifecycleListener(new FlutterNativeView.EngineLifecycleListenerImpl());
this.attach(this, isBackgroundView);
....
}
//c++關鍵方法2
private native long nativeAttach(FlutterJNI var1, boolean var2);
複製代碼
FlutterPluginRegistry是actitiy和flutterView綁定關係操做類,而FlutterJNI建立時,將綁定繪製、跨平臺通信、生命週期的監聽方法。這裏還會涉及到nativeAttach這個c++方法,等一會將會分析到。
繼續看runBundle的執行
//FlutterView.java
private FlutterNativeView mNativeView;
public void runFromBundle(FlutterRunArguments args) {
assertAttached();
preRun();
mNativeView.runFromBundle(args);
...
}
//FlutterNativeView.java
public void runFromBundle(FlutterRunArguments args) {
...
runFromBundleInternal(new String[] {args.bundlePath, args.defaultPath},
args.entrypoint, args.libraryPath);
...
}
/** * 這裏經過demo,咱們須要留意下傳入的數據,方便接下來的分析 * bundlePaths:(flutter_assets目錄地址) * entrypoint:"main" * libraryPath:null * */
private void runFromBundleInternal(String[] bundlePaths, String entrypoint, String libraryPath) {
....
mFlutterJNI.runBundleAndSnapshotFromLibrary(
bundlePaths,
entrypoint,
libraryPath,
mContext.getResources().getAssets()
);
....
}
複製代碼
此時,runFromBundle會先判斷資源的綁定,把一些參數經過runBundleAndSnapshotFromLibrary方法中mFlutterJNI
對象調用JNI方法來傳遞指定flutter入口供DartVM執行dart層代碼邏輯。
//FlutterJNI.java
@UiThread
public void runBundleAndSnapshotFromLibrary(@NonNull String[] prioritizedBundlePaths, @Nullable String entrypointFunctionName, @Nullable String pathToEntrypointFunction, @NonNull AssetManager assetManager) {
this.ensureAttachedToNative();
this.nativeRunBundleAndSnapshotFromLibrary(this.nativePlatformViewId, prioritizedBundlePaths, entrypointFunctionName, pathToEntrypointFunction, assetManager);
}
//最終樣例數據:pathToEntrypointFunction = null,entrypointFunctionName="main"
//prioritizedBundlePaths同上面,nativePlatformViewId = 3719055232
private native void nativeRunBundleAndSnapshotFromLibrary( long nativePlatformViewId, @NonNull String[] prioritizedBundlePaths, @Nullable String entrypointFunctionName, @Nullable String pathToEntrypointFunction, @NonNull AssetManager manager );
複製代碼
nativeRunBundleAndSnapshotFromLibrary
則是native啓動方法的入口,另外這個 nativePlatformViewId
是在FlutterNativeView
建立的時候調用了FlutterJNI
的attachToNative
方法,其來源是native層shell_holder對象指針,這個對象指針在native啓動過程當中很是關鍵。
再看MainActivity中onCreate執行,GeneratedPluginRegistrant.registerWith(this)將執行到以下代碼中
//FlutterActivityDelegate.java
private FlutterView flutterView;
@Override
public Registrar registrarFor(String pluginKey) {
return flutterView.getPluginRegistry().registrarFor(pluginKey);
}
//FlutterPluginRegistry.java
@Override
public Registrar registrarFor(String pluginKey) {
if (mPluginMap.containsKey(pluginKey)) {
throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
}
mPluginMap.put(pluginKey, null);
return new FlutterRegistrar(pluginKey);
}
複製代碼
registrarFor保存了插件的實例,避免重複註冊。
如下方法經過生命週期對應的Platform Channel發送生命週期狀態給Flutter層來告知當前的APP狀態。
this.mFlutterLifecycleChannel.send("AppLifecycleState.inactive");
複製代碼
public void onResume() {
Application app = (Application)this.activity.getApplicationContext();
FlutterMain.onResume(app);
if (app instanceof FlutterApplication) {
FlutterApplication flutterApp = (FlutterApplication)app;
flutterApp.setCurrentActivity(this.activity);
}
}
public static void onResume(Context context) {
//熱更新有關,這裏也不分析
if (sResourceUpdater != null && sResourceUpdater.getDownloadMode() == DownloadMode.ON_RESUME) {
sResourceUpdater.startUpdateDownloadOnce();
}
}
複製代碼
到這裏基本完成了java層分析,主要方法調用鏈能夠參考以下
接下來將須要分析的關鍵JNI方法羅列以下:
咱們直接找到對應的方法,位於shell/platform/android/flutter_main.cc
void FlutterMain::Init(JNIEnv* env,
jclass clazz,
jobject context,
jobjectArray jargs,
jstring bundlePath,
jstring appStoragePath,
jstring engineCachesPath) {
std::vector<std::string> args;
args.push_back("flutter");
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);
settings.assets_path = fml::jni::JavaStringToString(env, bundlePath);
...
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);
};
...
g_flutter_main.reset(new FlutterMain(std::move(settings)));
}
複製代碼
這裏作了幾件事情:
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;
}
}
//shell/platform/android/android_shell_holder.cc
AndroidShellHolder::AndroidShellHolder(
blink::Settings settings,
fml::jni::JavaObjectWeakGlobalRef java_object,
bool is_background_view)
: settings_(std::move(settings)), java_object_(java_object) {
...
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::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();
}
blink::TaskRunners task_runners(thread_label, // label platform_runner, // platform gpu_runner, // gpu ui_runner, // ui io_runner // io );
shell_ =
Shell::Create(task_runners, // task runners
settings_, // settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
...
}
std::unique_ptr<Shell> Shell::Create(
blink::TaskRunners task_runners,
blink::Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
PerformInitializationTasks(settings);
auto vm = blink::DartVM::ForProcess(settings);
FML_CHECK(vm) << "Must be able to initialize the VM.";
return Shell::Create(std::move(task_runners), //
std::move(settings), //
vm->GetIsolateSnapshot(), //
blink::DartSnapshot::Empty(), //
std::move(on_create_platform_view), //
std::move(on_create_rasterizer) //
);
}
複製代碼
nativeAttach的方法中,調用了AndroidShellHolder對象的建立,包含了JNI生命週期同UI和GPU線程綁定, 視圖回調和c++層繪製綁定,啓動一些必要的線程。而shell對象的建立中,PerformInitializationTasks包含了一些關鍵庫的初始化,如skia(圖形繪製庫)、ICU(國際化庫)等初始化,shell對象的建立也標誌着dart vm的建立。
關鍵點:AndroidShellHolder對象建立完成後,會將其對象指針值返回給java層保存,用於後續安卓原生層對Flutter層各操做方法的調用。
在shell/platform/android/io/platform_view_android_jni.cc中,咱們很容易找到對應的方法,是採用動態註冊的方式:
{
.name = "nativeRunBundleAndSnapshotFromLibrary",
.signature = "(J[Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Landroid/content/res/AssetManager;)V",
.fnPtr =
reinterpret_cast<void*>(&shell::RunBundleAndSnapshotFromLibrary),
}
複製代碼
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jobjectArray jbundlepaths,
jstring jEntrypoint,
jstring jLibraryUrl,
jobject jAssetManager) {
auto asset_manager = std::make_shared<blink::AssetManager>();
for (const auto& bundlepath :
fml::jni::StringArrayToVector(env, jbundlepaths)) {
...
const auto file_ext_index = bundlepath.rfind(".");
if (bundlepath.substr(file_ext_index) == ".zip") {
//資源解壓
asset_manager->PushBack(std::make_unique<blink::ZipAssetStore>(
bundlepath, "assets/flutter_assets"));
} else {
//操做資源地址並存儲到容器中
asset_manager->PushBack(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
bundlepath.c_str(), false, fml::FilePermission::kRead)));
...
}
}
auto isolate_configuration = CreateIsolateConfiguration(*asset_manager);
...
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)) {
//設置dart的入口函數,entrypoint爲「main」,引用庫地址
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));
}
複製代碼
從上面的方法咱們能夠簡單的總結下這個方法作了什麼:
android_shell_holder.cc
void AndroidShellHolder::Launch(RunConfiguration config) {
//is_valid_ = shell_ != nullptr;正常狀況下爲true
if (!IsValid()) {
return;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
fml::MakeCopyable([engine = shell_->GetEngine(), //拿到了引擎的弱引用對象
config = std::move(config)
]() mutable {
...
//next
if (!engine || engine->Run(std::move(config)) ==
shell::Engine::RunStatus::Failure) {
...
}
...
}));
}
複製代碼
Launch方法中拿到engine對象後,調用Run的執行
//engine.cc
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
...
auto isolate_launch_status =
PrepareAndLaunchIsolate(std::move(configuration));
....
}
shell::Engine::RunStatus Engine::PrepareAndLaunchIsolate(
RunConfiguration configuration) {
TRACE_EVENT0("flutter", "Engine::PrepareAndLaunchIsolate");
UpdateAssetManager(configuration.GetAssetManager());
auto isolate_configuration = configuration.TakeIsolateConfiguration();
std::shared_ptr<blink::DartIsolate> isolate =
runtime_controller_->GetRootIsolate().lock();
if (!isolate) {
return RunStatus::Failure;
}
...
if (!isolate_configuration->PrepareIsolate(*isolate)) {
FML_LOG(ERROR) << "Could not prepare to run the isolate.";
return RunStatus::Failure;
}
if (configuration.GetEntrypointLibrary().empty()) {
if (!isolate->Run(configuration.GetEntrypoint())) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
} else {
if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(),
configuration.GetEntrypoint())) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
}
return RunStatus::Success;
}
複製代碼
在engine的啓動過程當中,準備和啓動isolate,在這個方法中將完成對isolate建立、及狀態返回處理。更新資源管理後,PrepareIsolate方法主要檢查Isolate的狀態,經過屬性phase(枚舉)來表示不一樣的狀態,而後咱們再結合java層傳遞的數據,能夠知道將執行isolate->Run方法。
//dart_api_impl.cc
FML_WARN_UNUSED_RESULT
bool DartIsolate::Run(const std::string& entrypoint_name) {
...
auto user_entrypoint_function =
Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));
if (!InvokeMainEntrypoint(user_entrypoint_function)) {
return false;
}
...
}
複製代碼
Run方法中也比較簡單,繼續看下文。
//dart_isolate.cc
FML_WARN_UNUSED_RESULT static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function) {
...
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}))) {
FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
return false;
}
return true;
}
複製代碼
在InvokeMainEntrypoint方法中 會拿到了Dart_Handle對象,並經過DartInvokeField方法執行Dart_Invoke方法。另外Dart_LookupLibrary中建立的對象是一個Library,這個是下個方法執行步驟的判斷依據。
dart_api_impl.cc
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle* arguments) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
String& function_name =
String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
if (function_name.IsNull()) {
RETURN_TYPE_ERROR(Z, name, String);
}
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}
...
if (obj.IsType()) {
...
const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
...
//分析節點1
return Api::NewHandle(
T, cls.Invoke(function_name, args, arg_names, respect_reflectable,
check_is_entrypoint));
} else if (obj.IsNull() || obj.IsInstance()) {
...
Instance& instance = Instance::Handle(Z);
...
//分析節點2
return Api::NewHandle(
T, instance.Invoke(function_name, args, arg_names, respect_reflectable,
check_is_entrypoint));
} else if (obj.IsLibrary()) {
...
const Library& lib = Library::Cast(obj);
...
//分析節點3
return Api::NewHandle(
T, lib.Invoke(function_name, args, arg_names, respect_reflectable,
check_is_entrypoint));
}
...
}
複製代碼
在Dart_Invoke
方法中,會先進行狀態檢查 ,而後拿到由java層傳遞過來的dart 入口函數對應的方法名(也就"main"),注意在這個方法中,無論是錯誤仍是正確都是返回Dart_Handle
這個對像。而後再看這個三個分析節點,根據上面的分析,將會執行節點3
//object.cc
RawObject* Library::Invoke(const String& function_name,
const Array& args,
const Array& arg_names,
bool respect_reflectable,
bool check_is_entrypoint) const {
...
Function& function = Function::Handle(zone, LookupStaticFunction(function_name));
...
return DartEntry::InvokeFunction(function, args, args_descriptor_array);
...
}
複製代碼
Invoke方法將會經過方法名拿到內存中Function對象,而後經過dart執行該方法。
這裏留意下DartEntry這個類,看源碼的註釋大意是提取解析dart函數所需的功能的操做對象。是dart函數調用的重要對象之一,接着看看InvokeFunction作了什麼。
third_party/dart/runtime/vm/dart_entry.cc
RawObject* DartEntry::InvokeFunction(const Function& function,
const Array& arguments,
const Array& arguments_descriptor,
uword current_sp) {
...
#if defined(TARGET_ARCH_DBC)
//具體方法解析調用
return Simulator::Current()->Call(code, arguments_descriptor, arguments,
thread);
#elif defined(USING_SIMULATOR)
//模擬器
return bit_copy<RawObject*, int64_t>(Simulator::Current()->Call(
reinterpret_cast<intptr_t>(entrypoint), reinterpret_cast<intptr_t>(&code),
reinterpret_cast<intptr_t>(&arguments_descriptor),
reinterpret_cast<intptr_t>(&arguments),
reinterpret_cast<intptr_t>(thread)));
...
}
複製代碼
InvokeFunction 中將先會對Function對象內容是否編譯過進行判斷(未編譯將編譯從新調用),拿到當前線程去執行。該方法還會區分生產環境,是不是模擬器等狀況對方法進行解析,解析方法執行能夠參考Simulator::Current()->Call,在Call的方法內咱們能夠看到整個方法很是龐大,光方法體就有幾千行代碼,包含了常量值、字節碼等的操做,因此這一篇文章就不展開分析。有興趣的朋友能夠結合虛擬機原理,看看這部分是如何執行的。
至此咱們大體看到了整個啓動過程,在java層主要是對flutter資源相關的參數進行了賦值、初始化,以及回調方法的註冊,資源的拷貝,c++關鍵方法的調用,創建了通信體系(各種Channel)。而在c++層,咱們發現除去關鍵對象的建立,還有各種異常的處理(包含各類狀況的考量),參數的解析,資源的解析,方法對象的構建等一系列的調用,最後經過dart vm的操做對象對方法進行解析與執行。
蘇哲,銅板街Android開發工程師,2017年12月加入團隊,目前主要負責APP端 Android 平常開發。