Flutter启动流程简析

作者: juexingzhe | 来源:发表于2019-04-26 11:26 被阅读6次
    image

    今天基于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到私有目录下,看一个手机上私有目录下的截图

    image

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

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

    // FlutterActivity    
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            this.eventDelegate.onCreate(savedInstanceState);
    }
    
    // FlutterActivityDelegate
        @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 = 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<String> 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<Void, Void, Void> {...}
    

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

    image

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

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

    image

    再回到之前的代码那里,就是把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.cc
    static std::unique_ptr<FlutterMain> g_flutter_main;
    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);
    
      // 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.java
    private void attach(FlutterNativeView view, boolean isBackgroundView) {
            this.mFlutterJNI.attachToNative(isBackgroundView);
    }
    
    // FlutterJNI.java
    @UiThread
    public 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 Java
    
    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;
      }
    }
    

    接着看下很重要的一个类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.cc
    
    AndroidShellHolder::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,通过他可以往线程添加工作任务, 具体可以参考另外一篇Flutter和原生之间的平台通道实践与原理的线程部分。接着会构造Shell

    // android_shell_holder.cc
    
    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
          );
    
    // shell.cc
    
    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);
    
      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.cc
    DartVMRef DartVMRef::Create(Settings settings,
                                fml::RefPtr<DartSnapshot> vm_snapshot,
                                fml::RefPtr<DartSnapshot> isolate_snapshot,
                                fml::RefPtr<DartSnapshot> shared_snapshot) {
      std::lock_guard<std::mutex> 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<std::mutex> 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<IsolateNameServer>();
      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.cc
    
    DartVM::DartVM(std::shared_ptr<const DartVMData> vm_data,
                   std::shared_ptr<IsolateNameServer> isolate_name_server)
        : settings_(vm_data->GetSettings()),
          vm_data_(vm_data),
          isolate_name_server_(std::move(isolate_name_server)),
          service_protocol_(std::make_shared<ServiceProtocol>()) {
      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<decltype(params.create)>(
            DartIsolate::DartIsolateCreateCallback);
        params.shutdown = reinterpret_cast<decltype(params.shutdown)>(
            DartIsolate::DartIsolateShutdownCallback);
        params.cleanup = reinterpret_cast<decltype(params.cleanup)>(
            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.cc
    
    void 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.cc
    void 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> Shell::Create(
        blink::TaskRunners task_runners,
        blink::Settings settings,
        fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
        fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
        Shell::CreateCallback<PlatformView> on_create_platform_view,
        Shell::CreateCallback<Rasterizer> 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> 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.cc
    std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
        blink::DartVMRef vm,
        blink::TaskRunners task_runners,
        blink::Settings settings,
        fml::RefPtr<const blink::DartSnapshot> isolate_snapshot,
        fml::RefPtr<const blink::DartSnapshot> shared_snapshot,
        Shell::CreateCallback<PlatformView> on_create_platform_view,
        Shell::CreateCallback<Rasterizer> 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<Shell>(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.cc
    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;
            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.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<IOManager> 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<IOManager>(
                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> rasterizer;
      fml::WeakPtr<blink::SnapshotDelegate> 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> 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<Animator>(*shell, task_runners,
                                                       std::move(vsync_waiter));
    
            engine = std::make_unique<Engine>(*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/onCreate
    if (!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<String> 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.java
    public 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<void*>(&shell::RunBundleAndSnapshotFromLibrary),
    },
    
    // 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)) {
        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<blink::ZipAssetStore>(
              bundlepath, "assets/flutter_assets"));
    
        } else {
          asset_manager->PushBack(
              std::make_unique<blink::DirectoryAssetBundle>(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<blink::APKAssetProvider>(
                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::AndroidShellHolder*>(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.cc
    Engine::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.cc
    FML_WARN_UNUSED_RESULT
    bool 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_RESULT
    static 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层代码执行。

    参考链接:

    相关文章

      网友评论

        本文标题:Flutter启动流程简析

        本文链接:https://www.haomeiwen.com/subject/whrfnqtx.html