Android开发经验谈混合开发Android开发

Flutter启动流程简析

2019-04-26  本文已影响6人  juexingzhe
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.

// 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层代码执行。

参考链接:

上一篇下一篇

猜你喜欢

热点阅读