博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flutter启动流程简析
阅读量:5960 次
发布时间:2019-06-19

本文共 36575 字,大约阅读时间需要 121 分钟。

今天基于Android分析下Flutter的启动流程,首先看下官网提供的框架图,最下面一层Embedder是特定的平台实现,Android平台代码在engine/shell/platform/android下,其中有java的嫁接层在engine/shell/platform/android/io/flutter下面。Embedder层是Flutter启动的关键,在应用启动后通过该层初始化Flutter Engine,在Engine中会创建DartVM,在DartVM中执行dart编写的入口方法main方法,这样Flutter模块就启动成功。

1.Android平台代码分析

这部分代码是Embedder层的,在engine/shell/platform/android/io/flutter下面。

首先看到FlutterApplication中的onCreate

@CallSuper    public void onCreate() {        super.onCreate();        FlutterMain.startInitialization(this);    }复制代码

接着到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");            long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;            nativeRecordStartTimestamp(initTimeMillis);        }    }复制代码

在这里会进行配置信息初始化,初始化AOT模式或者JIT模式变量,资源文件初始化,主要是将asset目录下的flutter相关资源copy到私有目录下,看一个手机上私有目录下的截图

最后调用JNI方法nativeRecordStartTimestamp记录到C++层。

FlutterApplication执行完会执行MainActivity中的onCreate,主要工作会在父类FlutterActivity中,然后委托给FlutterActivityDelegate:

// FlutterActivity    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        this.eventDelegate.onCreate(savedInstanceState);}// FlutterActivityDelegate    @Overridepublic 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 = viewFactory.createFlutterView(activity);    if (flutterView == null) {        FlutterNativeView nativeView = viewFactory.createFlutterNativeView();        flutterView = new FlutterView(activity, null, nativeView);        flutterView.setLayoutParams(matchParent);        activity.setContentView(flutterView);        launchView = createLaunchView();        if (launchView != null) {            addLaunchView();        }    }    if (loadIntent(activity.getIntent())) {        return;    }    String appBundlePath = FlutterMain.findAppBundlePath(activity.getApplicationContext());    if (appBundlePath != null) {        runBundle(appBundlePath);    }}复制代码

可以看到有个setContentView,就是在这里设置内容视图,总结下FlutterActivityDelegate做的事:

1.根据系统版本设置状态栏样式

2.获取Intent

3.FlutterMain.ensureInitializationComplete

4.create FlutterNativeView

5.create FlutterView

6.设置activity的内容视图

7.执行appBundlePath

前面2步没什么说的,从第3步开始看。

2.FlutterMain

public static void ensureInitializationComplete(Context applicationContext, String[] args) {        if (Looper.myLooper() != Looper.getMainLooper()) {            throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");        } else if (sSettings == null) {            throw new IllegalStateException("ensureInitializationComplete must be called after startInitialization");        } else if (!sInitialized) {            try {                sResourceExtractor.waitForCompletion();                List
shellArgs = new ArrayList(); shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat"); if (args != null) { Collections.addAll(shellArgs, args); } if (sIsPrecompiledAsSharedLibrary) { shellArgs.add("--aot-shared-library-path=" + new File(PathUtils.getDataDirectory(applicationContext), sAotSharedLibraryPath)); } else { if (sIsPrecompiledAsBlobs) { shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext)); } else { shellArgs.add("--cache-dir-path=" + PathUtils.getCacheDirectory(applicationContext)); shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext) + "/" + sFlutterAssetsDir); } shellArgs.add("--vm-snapshot-data=" + sAotVmSnapshotData); shellArgs.add("--vm-snapshot-instr=" + sAotVmSnapshotInstr); shellArgs.add("--isolate-snapshot-data=" + sAotIsolateSnapshotData); shellArgs.add("--isolate-snapshot-instr=" + sAotIsolateSnapshotInstr); } if (sSettings.getLogTag() != null) { shellArgs.add("--log-tag=" + sSettings.getLogTag()); } String appBundlePath = findAppBundlePath(applicationContext); String appStoragePath = PathUtils.getFilesDir(applicationContext); String engineCachesPath = PathUtils.getCacheDirectory(applicationContext); nativeInit(applicationContext, (String[])shellArgs.toArray(new String[0]), appBundlePath, appStoragePath, engineCachesPath); sInitialized = true; } catch (Exception var6) { Log.e("FlutterMain", "Flutter initialization failed.", var6); throw new RuntimeException(var6); } } }复制代码

该方法必须要在主线程中执行并且只执行一次。并且要等sResourceExtractor把资源copy到安装包目录下完成后才能往下继续:

sResourceExtractor.waitForCompletion();void waitForCompletion() {        if (this.mExtractTask != null) {            try {                this.mExtractTask.get();            } catch (ExecutionException | InterruptedException | CancellationException var2) {                this.deleteFiles();            }        }    }private class ExtractTask extends AsyncTask
{...}复制代码

那么拷贝的是哪些东西呢?看一个debug下的apk:

其中vm开头的是dartvm执行需要的,isolate就是我们用dart语言编写的业务代码。

看下release包的apk,和debug有点不一样,多出了几个文件。

再回到之前的代码那里,就是把assets目录下的这些文件拷贝到安装包私有目录下的flutter_assets.

代码里面有很多的路径名:

private static final String DEFAULT_KERNEL_BLOB = "kernel_blob.bin";private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets";private static String sAotSharedLibraryPath = "app.so";private static String sAotVmSnapshotData = "vm_snapshot_data";private static String sAotVmSnapshotInstr = "vm_snapshot_instr";private static String sAotIsolateSnapshotData = "isolate_snapshot_data";private static String sAotIsolateSnapshotInstr = "isolate_snapshot_instr";private static String sFlx = "app.flx";private static String sFlutterAssetsDir = "flutter_assets";复制代码

接着会初始化一些目录,包括appBundle路径应用存储目录引擎缓存目录等。然后会调用JNI方法nativeInit在C++层初始化这些信息,在FlutterMain中把这些路径设置给setting,然后传递构造FlutterMain,再保存到全局变量g_flutter_main中。

// shell/platform/android/flutter_main.ccstatic std::unique_ptr
g_flutter_main;void FlutterMain::Init(JNIEnv* env, jclass clazz, jobject context, jobjectArray jargs, jstring bundlePath, jstring appStoragePath, jstring engineCachesPath) { std::vector
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); // Restore the callback cache. // TODO(chinmaygarde): Route all cache file access through FML and remove this // setter. blink::DartCallbackCache::SetCachePath( fml::jni::JavaStringToString(env, appStoragePath)); fml::paths::InitializeAndroidCachesPath( fml::jni::JavaStringToString(env, engineCachesPath)); blink::DartCallbackCache::LoadCacheFromDisk(); if (!blink::DartVM::IsRunningPrecompiledCode()) { // Check to see if the appropriate kernel files are present and configure // settings accordingly. auto application_kernel_path = fml::paths::JoinPaths({settings.assets_path, "kernel_blob.bin"}); 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); }; ... // 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)));}复制代码

接着看上面第四部create FlutterNativeView.

3.FlutterNativeView

public FlutterNativeView(Context context, boolean isBackgroundView) {        this.mNextReplyId = 1;        this.mPendingReplies = new HashMap();        this.mContext = context;        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);        this.assertAttached();        this.mMessageHandlers = new HashMap();    }复制代码

其中FlutterJNI是Java层和Flutter Engine通信的桥梁,包括创建并启动Flutter engine、当前FlutterView的Surface生命周期的通知、传递platform数据给dart层、回传dart层调用platform层方法返回的结果数据等待。

然后会调用attach方法:

// FlutterNativeView.javaprivate void attach(FlutterNativeView view, boolean isBackgroundView) {        this.mFlutterJNI.attachToNative(isBackgroundView);}// FlutterJNI.java@UiThreadpublic void attachToNative(boolean isBackgroundView) {     this.ensureNotAttachedToNative();     this.nativePlatformViewId = this.nativeAttach(this, isBackgroundView);}复制代码

attachToNative方法中通过调用JNI方法nativeAttach将当前flutterJNI对象传递给c++层(后续一些dart层调用java层的方法就是通过该对象调用对应的方法实现的),得到c++层返回的nativePlatformViewId,这个值非常重要,是c++层AndroidShellHolder的对象指针值,后续会通过该值调用一系列c++层的方法执行操作,并将其保存以供后续使用。

对应的C++方法如下, 通过之前初始化保存在g_flutter_main对象中的settings值和传入的java对象flutterJNI创建std::unique_ptr对象(该对象通过指针占有并管理AndroidShellHolder对象),该对象有效的情况下会调用release方法返回其管理对象的指针并释放对象的所有权,reinterpret_cast()方法将该AndroidShellHolder对象指针强制转化为long类型的值并返回java层保存。

// platform_view_android_jni.cc// Called By Javastatic 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
( FlutterMain::Get().GetSettings(), java_object, is_background_view); if (shell_holder->IsValid()) { return reinterpret_cast
(shell_holder.release()); } else { return 0; }}复制代码

接着看下很重要的一个类AndroiudShellHolder.

4.AndroiudShellHolder

代码比较长,先看下前半部分,传入的参数is_background_view为false,会首先通过ThreadHost初始化三个线程ui_thread,gpu_thread, io_thread,而当前线程就是platform_thread.

  • platform_thread负责和Engine层的通信
  • io_thread负责IO操作
  • gpu_thread执行GPU指令
  • ui_thread执行Dartisolate代码
// android_shell_holder.ccAndroidShellHolder::AndroidShellHolder(    blink::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++);  FML_CHECK(pthread_key_create(&thread_destruct_key_, ThreadDestructCallback) ==            0);  if (is_background_view) {    thread_host_ = {thread_label, ThreadHost::Type::UI};  } else {    thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |                                      ThreadHost::Type::IO};  }          ...}复制代码

四个线程会持有MessageLoop,通过他可以往线程添加工作任务, 具体可以参考另外一篇的线程部分。接着会构造Shell

// android_shell_holder.ccblink::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      );// shell.ccstd::unique_ptr
Shell::Create( blink::TaskRunners task_runners, blink::Settings settings, Shell::CreateCallback
on_create_platform_view, Shell::CreateCallback
on_create_rasterizer) { PerformInitializationTasks(settings); TRACE_EVENT0("flutter", "Shell::Create"); auto vm = blink::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(settings), // vm_data->GetIsolateSnapshot(), // isolate snapshot blink::DartSnapshot::Empty(), // shared snapshot std::move(on_create_platform_view), // std::move(on_create_rasterizer), // std::move(vm) // );}复制代码

Shell Create中会根据传入的settings参数通过blink::DartVMRef::Create构造Dart VM, 跟进去看看Dart VM的创建过程, VM只会构造一次,

// dart_vm_lifecycle.ccDartVMRef DartVMRef::Create(Settings settings,                            fml::RefPtr
vm_snapshot, fml::RefPtr
isolate_snapshot, fml::RefPtr
shared_snapshot) { std::lock_guard
lifecycle_lock(gVMMutex); // If there is already a running VM in the process, grab a strong reference to // it. 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)}; } std::lock_guard
dependents_lock(gVMDependentsMutex); gVMData.reset(); gVMServiceProtocol.reset(); gVMIsolateNameServer.reset(); gVM.reset(); // If there is no VM in the process. Initialize one, hold the weak reference // and pass a strong reference to the caller. auto isolate_name_server = std::make_shared
(); auto vm = DartVM::Create(std::move(settings), // std::move(vm_snapshot), // std::move(isolate_snapshot), // std::move(shared_snapshot), // isolate_name_server // ); if (!vm) { FML_LOG(ERROR) << "Could not create Dart VM instance."; return { nullptr}; } gVMData = vm->GetVMData(); gVMServiceProtocol = vm->GetServiceProtocol(); gVMIsolateNameServer = isolate_name_server; gVM = vm; if (settings.leak_vm) { gVMLeak = vm; } return DartVMRef{ std::move(vm)};}复制代码

然后通过DartVM::Create执行具体的构造过程,在Create中会调用DartVM构造函数, 通过执行dart::bin::BootstrapDartIo()方法引导启动dart:io时间处理程序:

//dart_vm.ccDartVM::DartVM(std::shared_ptr
vm_data, std::shared_ptr
isolate_name_server) : settings_(vm_data->GetSettings()), vm_data_(vm_data), isolate_name_server_(std::move(isolate_name_server)), service_protocol_(std::make_shared
()) { TRACE_EVENT0("flutter", "DartVMInitializer"); gVMLaunchCount++; FML_DCHECK(vm_data_); FML_DCHECK(isolate_name_server_); FML_DCHECK(service_protocol_); FML_DLOG(INFO) << "Attempting Dart VM launch for mode: " << (IsRunningPrecompiledCode() ? "AOT" : "Interpreter"); { TRACE_EVENT0("flutter", "dart::bin::BootstrapDartIo"); dart::bin::BootstrapDartIo(); if (!settings_.temp_directory_path.empty()) { dart::bin::SetSystemTempDirectory(settings_.temp_directory_path.c_str()); } }... DartUI::InitForGlobal(); { TRACE_EVENT0("flutter", "Dart_Initialize"); Dart_InitializeParams params = {}; params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION; params.vm_snapshot_data = vm_data_->GetVMSnapshot().GetData()->GetSnapshotPointer(); params.vm_snapshot_instructions = vm_data_->GetVMSnapshot().GetInstructionsIfPresent(); params.create = reinterpret_cast
( DartIsolate::DartIsolateCreateCallback); params.shutdown = reinterpret_cast
( DartIsolate::DartIsolateShutdownCallback); params.cleanup = reinterpret_cast
( DartIsolate::DartIsolateCleanupCallback); params.thread_exit = ThreadExitCallback; params.get_service_assets = GetVMServiceAssetsArchiveCallback; params.entropy_source = DartIO::EntropySource; char* init_error = Dart_Initialize(&params); ... } }复制代码

DartUI::InitForGlobal会注册dart的各种本地方法,主要用于dart调用c++层方法,有点类似于java中的jni注册:

// dart_ui.ccvoid DartUI::InitForGlobal() {  if (!g_natives) {    g_natives = new tonic::DartLibraryNatives();    Canvas::RegisterNatives(g_natives);    CanvasGradient::RegisterNatives(g_natives);    CanvasImage::RegisterNatives(g_natives);    CanvasPath::RegisterNatives(g_natives);    CanvasPathMeasure::RegisterNatives(g_natives);    Codec::RegisterNatives(g_natives);    DartRuntimeHooks::RegisterNatives(g_natives);    EngineLayer::RegisterNatives(g_natives);    FontCollection::RegisterNatives(g_natives);    FrameInfo::RegisterNatives(g_natives);    ImageFilter::RegisterNatives(g_natives);    ImageShader::RegisterNatives(g_natives);    IsolateNameServerNatives::RegisterNatives(g_natives);    Paragraph::RegisterNatives(g_natives);    ParagraphBuilder::RegisterNatives(g_natives);    Picture::RegisterNatives(g_natives);    PictureRecorder::RegisterNatives(g_natives);    Scene::RegisterNatives(g_natives);    SceneBuilder::RegisterNatives(g_natives);    SceneHost::RegisterNatives(g_natives);    SemanticsUpdate::RegisterNatives(g_natives);    SemanticsUpdateBuilder::RegisterNatives(g_natives);    Versions::RegisterNatives(g_natives);    Vertices::RegisterNatives(g_natives);    Window::RegisterNatives(g_natives);    // Secondary isolates do not provide UI-related APIs.    g_natives_secondary = new tonic::DartLibraryNatives();    DartRuntimeHooks::RegisterNatives(g_natives_secondary);    IsolateNameServerNatives::RegisterNatives(g_natives_secondary);  }}// window.ccvoid Window::RegisterNatives(tonic::DartLibraryNatives* natives) {  natives->Register({      {
"Window_defaultRouteName", DefaultRouteName, 1, true}, {
"Window_scheduleFrame", ScheduleFrame, 1, true}, {
"Window_sendPlatformMessage", _SendPlatformMessage, 4, true}, {
"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true}, {
"Window_render", Render, 2, true}, {
"Window_updateSemantics", UpdateSemantics, 2, true}, {
"Window_setIsolateDebugName", SetIsolateDebugName, 2, true}, {
"Window_reportUnhandledException", ReportUnhandledException, 2, true}, });}复制代码

然后再DartVM中通过Dart_Initialize初始化Dart运行时环境,后面就不往下跟了,返回到shell.cc中,构造玩vm后会赋值给Shell, 再通过CreateShellOnPlatformThread构造Shell,该方法会在PlatformThread线程中执行。

std::unique_ptr
Shell::Create( blink::TaskRunners task_runners, blink::Settings settings, fml::RefPtr
isolate_snapshot, fml::RefPtr
shared_snapshot, Shell::CreateCallback
on_create_platform_view, Shell::CreateCallback
on_create_rasterizer, blink::DartVMRef vm) { PerformInitializationTasks(settings); TRACE_EVENT0("flutter", "Shell::CreateWithSnapshots"); if (!task_runners.IsValid() || !on_create_platform_view || !on_create_rasterizer) { return nullptr; } fml::AutoResetWaitableEvent latch; std::unique_ptr
shell; fml::TaskRunner::RunNowOrPostTask( task_runners.GetPlatformTaskRunner(), fml::MakeCopyable([&latch, // vm = std::move(vm), // &shell, // task_runners = std::move(task_runners), // settings, // isolate_snapshot = std::move(isolate_snapshot), // shared_snapshot = std::move(shared_snapshot), // on_create_platform_view, // on_create_rasterizer // ]() mutable { shell = CreateShellOnPlatformThread(std::move(vm), std::move(task_runners), // settings, // std::move(isolate_snapshot), // std::move(shared_snapshot), // on_create_platform_view, // on_create_rasterizer // ); latch.Signal(); })); latch.Wait(); return shell;}复制代码

接下来到CreateShellOnPlatformThread看看,代码比较多分成几个部分来看, 首先调用new Shell构造,然后调用on_create_platform_view,这个方法在android_shell_holder.cc中通过Shell::Create传递过来的

// shell.ccstd::unique_ptr
Shell::CreateShellOnPlatformThread( blink::DartVMRef vm, blink::TaskRunners task_runners, blink::Settings settings, fml::RefPtr
isolate_snapshot, fml::RefPtr
shared_snapshot, Shell::CreateCallback
on_create_platform_view, Shell::CreateCallback
on_create_rasterizer) { if (!task_runners.IsValid()) { FML_LOG(ERROR) << "Task runners to run the shell were invalid."; return nullptr; } auto shell = std::unique_ptr
(new Shell(std::move(vm), task_runners, settings)); // Create the platform view on the platform thread (this thread). auto platform_view = on_create_platform_view(*shell.get()); if (!platform_view || !platform_view->GetWeakPtr()) { return nullptr; } ...}复制代码

看下on_create_platform_view,在这里会构造PlatformViewAndroid并且交给platform_view管理

// android_shell_holder.ccfml::WeakPtr
weak_platform_view; Shell::CreateCallback
on_create_platform_view = [is_background_view, java_object, &weak_platform_view](Shell& shell) { std::unique_ptr
platform_view_android; if (is_background_view) { platform_view_android = std::make_unique
( shell, // delegate shell.GetTaskRunners(), // task runners java_object // java object handle for JNI interop ); } else { platform_view_android = std::make_unique
( 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.cc中接着往下看,接着会在IO Thread中构造IOManager对象并且交给io_manager管理:

// Create the IO manager on the IO thread. The IO manager must be initialized  // first because it has state that the other subsystems depend on. It must  // first be booted and the necessary references obtained to initialize the  // other subsystems.  fml::AutoResetWaitableEvent io_latch;  std::unique_ptr
io_manager; auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner(); fml::TaskRunner::RunNowOrPostTask( io_task_runner, [&io_latch, // &io_manager, // &platform_view, // io_task_runner // ]() { TRACE_EVENT0("flutter", "ShellSetupIOSubsystem"); io_manager = std::make_unique
( platform_view->CreateResourceContext(), io_task_runner); io_latch.Signal(); }); io_latch.Wait();复制代码

接着会在GPU Thread中构造Rasterizer对象并且交给rasterizer管理,on_create_rasterizer也是在android_shell_holder.cc中通过Shell::Create传递过来的

// Create the rasterizer on the GPU thread.  fml::AutoResetWaitableEvent gpu_latch;  std::unique_ptr
rasterizer; fml::WeakPtr
snapshot_delegate; fml::TaskRunner::RunNowOrPostTask( task_runners.GetGPUTaskRunner(), [&gpu_latch, // &rasterizer, // on_create_rasterizer, // shell = shell.get(), // &snapshot_delegate // ]() { TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem"); if (auto new_rasterizer = on_create_rasterizer(*shell)) { rasterizer = std::move(new_rasterizer); snapshot_delegate = rasterizer->GetSnapshotDelegate(); } gpu_latch.Signal(); }); gpu_latch.Wait();复制代码

接着在UIThread中创建Engine,并且交给engine管理:

// Create the engine on the UI thread.  fml::AutoResetWaitableEvent ui_latch;  std::unique_ptr
engine; fml::TaskRunner::RunNowOrPostTask( shell->GetTaskRunners().GetUITaskRunner(), fml::MakeCopyable([&ui_latch, // &engine, // shell = shell.get(), // isolate_snapshot = std::move(isolate_snapshot), // shared_snapshot = std::move(shared_snapshot), // vsync_waiter = std::move(vsync_waiter), // snapshot_delegate = std::move(snapshot_delegate), // io_manager = io_manager->GetWeakPtr() // ]() mutable { TRACE_EVENT0("flutter", "ShellSetupUISubsystem"); const auto& task_runners = shell->GetTaskRunners(); // The animator is owned by the UI thread but it gets its vsync pulses // from the platform. auto animator = std::make_unique
(*shell, task_runners, std::move(vsync_waiter)); engine = std::make_unique
(*shell, // *shell->GetDartVM(), // std::move(isolate_snapshot), // std::move(shared_snapshot), // task_runners, // shell->GetSettings(), // std::move(animator), // std::move(snapshot_delegate), // std::move(io_manager) // ); ui_latch.Signal(); })); ui_latch.Wait();复制代码

最后通过shell->Setup方法将platform_view engine rasterizer io_manager四个对象交给 Shell对象管理:

// We are already on the platform thread. So there is no platform latch to  // wait on.  if (!shell->Setup(std::move(platform_view),  //                    std::move(engine),         //                    std::move(rasterizer),     //                    std::move(io_manager))     //  ) {    return nullptr;  }  return shell;复制代码

再回到前面的android_shell_holder.cc中,通过Shell::Create()创建完成后的shell对象返回给AndroidShellHolder对象持有。到这里整体思路就清晰了,Embedder层通过Shell对象与Engine层建立了连接,后续的一切操作通过Shell对象进行。而Shell对象又通过AndroidShellHolder对象持有,AndroidShellHolder对象指针值又返回给了java层,然后java层在调用JNI方法的时候将这个指针值传递过去便能拿到Embedder层的AndroidShellHolder对象,进而通过Shell对象向engine层发送一系列操作指令。

5.RunBundle

经过上面的流程,已经为dart层代码执行创建好了运行时环境,接下来就是加载dart层相关的代码了。

再回到java层的FlutterActivityDelegate中的onCreate代码:

//FlutterActivityDelegate.java/onCreateif (!this.loadIntent(this.activity.getIntent())) {            String appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());            if (appBundlePath != null) {                this.runBundle(appBundlePath);            }        }//FlutterActivityDelegate.java/runBundle    private void runBundle(String appBundlePath) {        if (!this.flutterView.getFlutterNativeView().isApplicationRunning()) {            FlutterRunArguments args = new FlutterRunArguments();            ArrayList
bundlePaths = new ArrayList(); ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater(); if (resourceUpdater != null) { File patchFile = resourceUpdater.getInstalledPatch(); JSONObject manifest = resourceUpdater.readManifest(patchFile); if (resourceUpdater.validateManifest(manifest)) { bundlePaths.add(patchFile.getPath()); } } bundlePaths.add(appBundlePath); args.bundlePaths = (String[])bundlePaths.toArray(new String[0]); args.entrypoint = "main"; this.flutterView.runFromBundle(args); } }复制代码

调用自己的runBundle函数,在if语句里面可以看到资源提取的代码,这里是Flutter预埋的动态更新代码,目前应该还没起作用,然后会调用FlutterView runFromBundle

// FlutterView.javapublic void runFromBundle(FlutterRunArguments args) {        this.assertAttached();        this.preRun();        this.mNativeView.runFromBundle(args);        this.postRun();}复制代码

java层最终会调到FlutterJNI中,其中nativePlatformViewId就是AndroidShellHolderjava层的指针值,此时的prioritizedBundlePaths数组中只有一个值类似/data/data/包名/flutter/flutter_assets/的路径值,entrypointFunctionNamemainpathToEntrypointFunctionnull

// FlutterJNI.java  @UiThread  public void runBundleAndSnapshotFromLibrary(      @NonNull String[] prioritizedBundlePaths,      @Nullable String entrypointFunctionName,      @Nullable String pathToEntrypointFunction,      @NonNull AssetManager assetManager  ) {    ensureAttachedToNative();    nativeRunBundleAndSnapshotFromLibrary(        nativePlatformViewId,        prioritizedBundlePaths,        entrypointFunctionName,        pathToEntrypointFunction,        assetManager    );  }  private native void nativeRunBundleAndSnapshotFromLibrary(      long nativePlatformViewId,      @NonNull String[] prioritizedBundlePaths,      @Nullable String entrypointFunctionName,      @Nullable String pathToEntrypointFunction,      @NonNull AssetManager manager  );复制代码

后面就到了JNI层了,在PlatformViewAndrod中:

// 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
(&shell::RunBundleAndSnapshotFromLibrary),},// RunBundleAndSnapshotFromLibrarystatic void RunBundleAndSnapshotFromLibrary(JNIEnv* env, jobject jcaller, jlong shell_holder, jobjectArray jbundlepaths, jstring jEntrypoint, jstring jLibraryUrl, jobject jAssetManager) { auto asset_manager = std::make_shared
(); for (const auto& bundlepath : fml::jni::StringArrayToVector(env, jbundlepaths)) { if (bundlepath.empty()) { continue; } // If we got a bundle path, attempt to use that as a directory asset // bundle or a zip asset bundle. const auto file_ext_index = bundlepath.rfind("."); if (bundlepath.substr(file_ext_index) == ".zip") { asset_manager->PushBack(std::make_unique
( bundlepath, "assets/flutter_assets")); } else { asset_manager->PushBack( std::make_unique
(fml::OpenDirectory( bundlepath.c_str(), false, fml::FilePermission::kRead))); // Use the last path component of the bundle path to determine the // directory in the APK assets. const auto last_slash_index = bundlepath.rfind("/", bundlepath.size()); if (last_slash_index != std::string::npos) { auto apk_asset_dir = bundlepath.substr( last_slash_index + 1, bundlepath.size() - last_slash_index); asset_manager->PushBack(std::make_unique
( env, // jni environment jAssetManager, // asset manager std::move(apk_asset_dir)) // apk asset dir ); } } }复制代码

上面逻辑首先通过bundlePath创建DirectoryAssetBundle对象交给asset_manager对象管理,然后欻功能键运行配置对象config,通过ANDROID_SHELL_HOLDER->Launch(std::move(config));根据运行配置信息启动,ANDROID_SHELL_HOLDER是一个宏,通过将java层持有的AndroidShellHolder指针值强转为AndroidShellHolder对象指针,这样就可以调用它的方法了。

// platform_view_android_jni.cc#define ANDROID_SHELL_HOLDER \  (reinterpret_cast
(shell_holder))复制代码

再看到AndroidShellHolder中的方法Launch,就是到shell中取出engine,然后在UIThread中运行engine->Run:

void AndroidShellHolder::Launch(RunConfiguration config) {  if (!IsValid()) {    return;  }  shell_->GetTaskRunners().GetUITaskRunner()->PostTask(      fml::MakeCopyable([engine = shell_->GetEngine(),  //                         config = std::move(config)     //  ]() mutable {        FML_LOG(INFO) << "Attempting to launch engine configuration...";        if (!engine || engine->Run(std::move(config)) ==                           shell::Engine::RunStatus::Failure) {          FML_LOG(ERROR) << "Could not launch engine in configuration.";        } else {          FML_LOG(INFO) << "Isolate for engine configuration successfully "                           "started and run.";        }      }));}复制代码

再看下engine->Run:

// engine.ccEngine::RunStatus Engine::Run(RunConfiguration configuration) {  if (!configuration.IsValid()) {    FML_LOG(ERROR) << "Engine run configuration was invalid.";    return RunStatus::Failure;  }  auto isolate_launch_status =      PrepareAndLaunchIsolate(std::move(configuration)); ...  return isolate_running ? Engine::RunStatus::Success                         : Engine::RunStatus::Failure;}shell::Engine::RunStatus Engine::PrepareAndLaunchIsolate(    RunConfiguration configuration) {  ...  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;}复制代码

最终调到DartIsolateRun方法, 通过DartInvokeField执行到Dart层的main()方法入口,这样整个Dart代码就跑起来了,Flutter界面也就显示到FlutterView中。

// dart_isolate.ccFML_WARN_UNUSED_RESULTbool DartIsolate::Run(const std::string& entrypoint_name, fml::closure on_run) {  TRACE_EVENT0("flutter", "DartIsolate::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()));  if (!InvokeMainEntrypoint(user_entrypoint_function)) {    return false;  }  phase_ = Phase::Running;  FML_DLOG(INFO) << "New isolate is in the running state.";  if (on_run) {    on_run();  }  return true;}FML_WARN_UNUSED_RESULTstatic bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function) {  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}))) {    FML_LOG(ERROR) << "Could not invoke the main entrypoint.";    return false;  }  return true;}复制代码

6.总结

整个代码比较长,简单总结就是在Android平台上Flutter是显示到FlutterView上的,FlutterView会通过FlutterNativeView调用到FlutterJNI,在FlutterJNI会持有一个很重要的对象AndroidShellHolder,而 AndroidShellHolder会持有shell对象, Embedder层通过Shell对象与Engine层建立了连接,后续的一切操作通过Shell对象进行。AndroidShellHolder对象指针值又返回给了java层,然后FlutterJNI在调用JNI方法的时候将这个指针值传递过去便能拿到Embedder层的AndroidShellHolder对象,进而通过Shell对象向engine层发送一系列操作指令。Engine对象会调用dart层代码执行。

参考链接:

转载于:https://juejin.im/post/5cc278a6f265da0378759c87

你可能感兴趣的文章
spark rdd saveAsTextFile保存为文件
查看>>
ArcGIS “Error HRESULT E_FAIL has been returned from a call to a COM component.” 异常的解决
查看>>
NeHe OpenGL教程 第十七课:2D图像文字
查看>>
.NET开源项目(转)
查看>>
补码[基础]
查看>>
两个乒乓球队进行比赛问题
查看>>
POJ2709 Painter 贪心算法
查看>>
oc-10-对象做参数
查看>>
Windows Azure Cloud Service (10) Role的生命周期
查看>>
二、Axis2的简单WebService示例
查看>>
接口的显示实现和隐式实现
查看>>
安装EBS前期检查工具 - RDA - Health Check / Validation Engine Guide 2 结果
查看>>
Windows Phone笔记(11)使用独立存储(下)
查看>>
currentRowChanged 的注意事项
查看>>
面试题--在一个字符串中查找重复次数最多的字符(转)
查看>>
Beam内置的数据源清单(Java、Python)
查看>>
二维数组
查看>>
Ambari集群里操作时典型权限问题put: `/home/bigdata/1.txt': No such file or directory的解决方案(图文详解)...
查看>>
Objective-C:运行时runtime
查看>>
c++ 基于wincrypt的DES CBC模式加解密
查看>>