您好,登錄后才能下訂單哦!
這篇文章主要介紹“Flutter在Android平臺上啟動時,Native層做了哪些工作”,在日常操作中,相信很多人在Flutter在Android平臺上啟動時,Native層做了哪些工作問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”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<FlutterLoader.InitResult> initTask = new Callable<FlutterLoader.InitResult>() { 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<String> 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方法嗎?
FlutterMain::Register
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<void*>(&Init), }, { .name = "nativePrefetchDefaultFontManager", .signature = "()V", .fnPtr = reinterpret_cast<void*>(&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(&Init),便會拉起它的FlutterMain::Init方法。
void FlutterMain::Init(JNIEnv* env, jclass clazz, jobject context, jobjectArray jargs, jstring kernelPath, jstring appStoragePath, jstring engineCachesPath, jlong initTimeMillis) { std::vector<std::string> 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<fml::NonOwnedMapping>(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()。
FlutterActivity& 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<PlatformViewAndroidJNI> jni_facade = std::make_shared<PlatformViewAndroidJNIImpl>(java_object); ///主要就是初始化一個 shell holder auto shell_holder = std::make_unique<AndroidShellHolder>( FlutterMain::Get().GetSettings(), jni_facade, is_background_view); if (shell_holder->IsValid()) { return reinterpret_cast<jlong>(shell_holder.release()); } else { return 0; } }
我們來看一下AndroidShellHolder.cc的實現
AndroidShellHolder & gpu/ui/io線程的創建
它有一個100多行的構造函數:
AndroidShellHolder::AndroidShellHolder( flutter::Settings settings, std::shared_ptr<PlatformViewAndroidJNI> 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<void*>(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<PlatformViewAndroid> weak_platform_view; Shell::CreateCallback<PlatformView> on_create_platform_view = [is_background_view, &jni_facade, &weak_platform_view](Shell& shell) { std::unique_ptr<PlatformViewAndroid> platform_view_android; if (is_background_view) { ...走下面 } else { ///初始化了一個PlatformViewAndroid platform_view_android = std::make_unique<PlatformViewAndroid>( 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<Rasterizer> on_create_rasterizer = [](Shell& shell) { return std::make_unique<Rasterizer>(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<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_.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
我們接著看一下 shell_的創建:
std::unique_ptr<Shell> Shell::Create( TaskRunners task_runners, const PlatformData platform_data, Settings settings, Shell::CreateCallback<PlatformView> on_create_platform_view, Shell::CreateCallback<Rasterizer> 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::Create
DartVMRef DartVMRef::Create(Settings settings, fml::RefPtr<DartSnapshot> vm_snapshot, fml::RefPtr<DartSnapshot> 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<IsolateNameServer>(); 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。
Shell & CreateShellOnPlatformThread
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread( DartVMRef vm, TaskRunners task_runners, const PlatformData platform_data, Settings settings, fml::RefPtr<const DartSnapshot> isolate_snapshot, const Shell::CreateCallback<PlatformView>& on_create_platform_view, const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) { ... ///創建對象 auto shell = std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings)); // 創建rasterizer :工作在gpu線程 // 這里要說一下,gpu線程還是在cpu上的,只是這個線程叫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.GetRasterTaskRunner(), [&rasterizer_promise, // &snapshot_delegate_promise, on_create_rasterizer, // shell = shell.get() // ]() { TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem"); 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)創建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<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(); // 在ui線程創建engine // 這里的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, // &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<Animator>(*shell, task_runners, std::move(vsync_waiter)); engine_promise.set_value(std::make_unique<Engine>( *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::Engine(Delegate& delegate, const PointerDataDispatcherMaker& dispatcher_maker, DartVM& vm, fml::RefPtr<const DartSnapshot> isolate_snapshot, TaskRunners task_runners, const PlatformData platform_data, Settings settings, std::unique_ptr<Animator> animator, fml::WeakPtr<IOManager> io_manager, fml::RefPtr<SkiaUnrefQueue> unref_queue, fml::WeakPtr<SnapshotDelegate> snapshot_delegate) : Engine(delegate, dispatcher_maker, vm.GetConcurrentWorkerTaskRunner(), task_runners, settings, std::move(animator), io_manager, nullptr) { 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), // 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個:
platform 線程(當前線程)
ui 線程
gpu 線程
io 線程
并初始化一系列重要對象。
好的,我們再回到主線,onCreate()已經過了,下面我們可以看一下onStart()生命周期:
此方法會調用 delegate.onStart(); 并最終調用FlutterJNI的native方法:
private native void nativeRunBundleAndSnapshotFromLibrary( long nativePlatformViewId, @NonNull String bundlePath, @Nullable String entrypointFunctionName, @Nullable String pathToEntrypointFunction, @NonNull AssetManager manager);
從這里開始,其終點就是執行dart的代碼。
Launch
接著我們看一下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<void(Engine::RunStatus)>& 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); })); }
Engin.run()
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; }
LaunchRootIsolate
bool RuntimeController::LaunchRootIsolate( const Settings& settings, std::optional<std::string> dart_entrypoint, std::optional<std::string> dart_entrypoint_library, std::unique_ptr<IsolateConfiguration> 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<PlatformConfiguration>(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方法
DartIsolate::CreateRunningRootIsolate
std::weak_ptr<DartIsolate> DartIsolate::CreateRunningRootIsolate( const Settings& settings, fml::RefPtr<const DartSnapshot> isolate_snapshot, TaskRunners task_runners, std::unique_ptr<PlatformConfiguration> platform_configuration, fml::WeakPtr<SnapshotDelegate> snapshot_delegate, fml::WeakPtr<HintFreedDelegate> hint_freed_delegate, fml::WeakPtr<IOManager> io_manager, fml::RefPtr<SkiaUnrefQueue> skia_unref_queue, fml::WeakPtr<ImageDecoder> 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<std::string> dart_entrypoint, std::optional<std::string> dart_entrypoint_library, std::unique_ptr<IsolateConfiguration> 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<std::string> library_name, std::optional<std::string> entrypoint, const std::vector<std::string>& 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在Android平臺上啟動時,Native層做了哪些工作”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。