Flutter在Android平台上启动时,Native层做了什么?

3,218 阅读10分钟

前言

接上回 Flutter——在Android平台上的启动流程浅析,

我们来看看穿插在其中的native层都做了什么。

由于代码较多,我会将说明以注释的形式写在代码里,并删除非必要代码

FlutterLoader

在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 & onCreate

这里需要提一下,目前你搜索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<void*>(&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()生命周期:

Flutter——在Android平台上的启动流程浅析

FlutterActivity & 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的启动从平台到native所作的工作基本就简要的介绍完了。

本人也是刚开始对native进行了解,以进一步对flutter的运行原理有所了解,如果有错误之处,还请指出,谢谢。

系列文章

Flutter 仿网易云音乐App

Flutter&Android 启动页(闪屏页)的加载流程和优化方案

Flutter版 仿.知乎列表的视差效果

Flutter——实现网易云音乐的渐进式卡片切换

Flutter 仿同花顺自选股列表