Flutter之引擎啟動流程

大逗大人發表於2020-03-12

在Android中,應用的啟動都是從Application的建立開始,所以基本上都會來自定義實現Application並在該類中進行一些初始化操作,如推送、分享、支付等。Flutter也不例外,也會在自定義的Application中進行引擎的初始化操作。

1、引擎的初始化

FlutterApplication就是一個自定義的Application類,在該類中進行了引擎的初始化,程式碼如下。

public class FlutterApplication extends Application {
    @Override
    @CallSuper
    public void onCreate() {
        super.onCreate();
        //初始化
        FlutterMain.startInitialization(this);
    }

    ...
}
複製程式碼

再來看FlutterMain類的startInitialization方法,因為引擎的初始化是通過該方法開始的。

public static void startInitialization(@NonNull Context applicationContext) {
    //如果在進行Robolectric測試,則暫不進行初始化操作
    if (isRunningInRobolectricTest) {
        return;
    }
    FlutterLoader.getInstance().startInitialization(applicationContext);
}
複製程式碼

startInitialization方法中又呼叫了FlutterLoaderstartInitialization方法,該方法是引擎初始化的具體實現。

public class FlutterLoader {

    ...
    public void startInitialization(@NonNull Context applicationContext) {
        startInitialization(applicationContext, new Settings());
    }
    public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
        //不允許多次初始化
        if (this.settings != null) {
          return;
        }
        //必須在主執行緒中初始化
        if (Looper.myLooper() != Looper.getMainLooper()) {
          throw new IllegalStateException("startInitialization must be called on the main thread");
        }

        this.settings = settings;
        
        //當前時間
        long initStartTimestampMillis = SystemClock.uptimeMillis();
        //初始化配置
        initConfig(applicationContext);
        //初始化資源
        initResources(applicationContext);
        
        //載入flutter.so動態庫
        System.loadLibrary("flutter");
        
        //初始化一個類VsyncWaiter,主要是同步Android的VSYNC訊號給Engine
        VsyncWaiter
            .getInstance((WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE))
            .init();

        //記錄Engine的初始化時間
        long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
        FlutterJNI.nativeRecordStartTimestamp(initTimeMillis);
    }
    
    ...
}
複製程式碼

這裡重點在於flutter.so動態庫的載入。由於Java VM在載入動態庫時第一個呼叫的是JNI_OnLoad函式,所以就先來看該函式的實現。

[-> flutter/shell/platform/android/library_loader.cc]

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
  //Initialize the Java VM.
  //將vm作為一個全域性變數
  fml::jni::InitJavaVM(vm);
  
  //獲取當前執行緒的env
  JNIEnv* env = fml::jni::AttachCurrentThread();
  bool result = false;

  //Register FlutterMain.
  //Java Native方法的註冊,主要是註冊了FlutterJNI類的nativeInit、nativeRecordStartTimestamp方法。
  result = flutter::FlutterMain::Register(env);

  //Register PlatformView
  //Java Native方法的註冊
  result = flutter::PlatformViewAndroid::Register(env);

  //Register VSyncWaiter.
  //Java Native方法的註冊
  result = flutter::VsyncWaiterAndroid::Register(env);

  return JNI_VERSION_1_4;
}
複製程式碼

到此,引擎就已經成功初始化,流程圖如下。

Flutter之引擎啟動流程

2、Engine物件的建立

引擎初始化成功後,就可以來建立引擎。在Android中,引擎是從FlutterActivityonCreate方法開始建立的,程式碼如下。

public class FlutterActivity extends Activity implements FlutterView.Provider, PluginRegistry, ViewFactory {

    private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
    
    private final FlutterActivityEvents eventDelegate = delegate;
    private final FlutterView.Provider viewProvider = delegate;
    private final PluginRegistry pluginRegistry = delegate;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        eventDelegate.onCreate(savedInstanceState);
    }
}
複製程式碼

顧名思義,FlutterActivityDelegate是一個代理類,全權負責FlutterActivity的所有工作。由於Activity在其生命週期內呼叫的第一個方法是onCreate。所以來看類FlutterActivityDelegate中的onCreate方法的具體實現。

public final class FlutterActivityDelegate
        implements FlutterActivityEvents,
                   FlutterView.Provider,
                   PluginRegistry {
    @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,預設不需要自定義
        flutterView = viewFactory.createFlutterView(activity);
        if (flutterView == null) {
            //是否自定義FlutterNativeView,預設不自定義
            FlutterNativeView nativeView = viewFactory.createFlutterNativeView();
            //建立flutterView
            flutterView = new FlutterView(activity, null, nativeView);
            //flutterView鋪滿整個螢幕
            flutterView.setLayoutParams(matchParent);
            activity.setContentView(flutterView);
            //建立launchView,launchView是Flutter載入第一幀前的展示View
            launchView = createLaunchView();
            if (launchView != null) {
                addLaunchView();
            }
        }

        if (loadIntent(activity.getIntent())) {
            return;
        }
        
        //獲取flutter程式碼路徑
        String appBundlePath = FlutterMain.findAppBundlePath();
        if (appBundlePath != null) {
            //執行Flutter程式碼
            runBundle(appBundlePath);
        }
    }
}
複製程式碼

onCreate方法中,主要做了以下兩件事。

  1. 建立了一個FlutterView,該View是Flutter介面在Android端的載體。
  2. Flutter程式碼的執行,其實現原理後面再詳解。

先來看FlutterView的建立,它繼承自SurfaceView,程式碼如下。

public class FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry {
    public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
        super(context, attrs);

        Activity activity = getActivity(getContext());
        if (activity == null) {
            throw new IllegalArgumentException("Bad context");
        }

        if (nativeView == null) {
            //建立FlutterNativeView物件
            mNativeView = new FlutterNativeView(activity.getApplicationContext());
        } else {
            mNativeView = nativeView;
        }

        ...
    }
}
複製程式碼

FlutterView中,會建立一個FlutterNativeView物件,其建構函式的實現如下。

public class FlutterNativeView implements BinaryMessenger {
    public FlutterNativeView(@NonNull Context context) {
        this(context, false);
    }

    public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
        mContext = context;
        //建立FlutterPluginRegistry物件
        mPluginRegistry = new FlutterPluginRegistry(this, context);
        //建立FlutterJNI物件
        mFlutterJNI = new FlutterJNI();
        mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
        //建立DartExecutor物件,該物件主要用於Android與Flutter間的通訊,如生命週期。
        this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets());
        //新增Engine生命週期監聽
        mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
        //執行attach方法
        attach(this, isBackgroundView);
        assertAttached();
    }
    private void attach(FlutterNativeView view, boolean isBackgroundView) {
        mFlutterJNI.attachToNative(isBackgroundView);
        dartExecutor.onAttachedToJNI();
    }
}

//主要是用於Android與Native間的相互呼叫
public class FlutterJNI {
  @UiThread
  public void attachToNative(boolean isBackgroundView) {
    ...
    nativePlatformViewId = nativeAttach(this, isBackgroundView);
  }
  
  //native方法
  private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
}
複製程式碼

這裡重點在於attach方法,該方法會通過FlutterJNInativeAttach方法來進行UI、GPU、IO等執行緒的建立、Dart VM的建立及Engine物件的建立等。下面先來看nativeAttach方法在引擎中的對應實現。

[-> flutter/shell/platform/android/platform_view_android_jni.cc]

static jlong AttachJNI(JNIEnv* env,
                       jclass clazz,
                       jobject flutterJNI,
                       jboolean is_background_view) {
  fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
  //AndroidShellHolder物件的建立
  auto shell_holder = std::make_unique<AndroidShellHolder>(
      FlutterMain::Get().GetSettings(), java_object, is_background_view);
  ...
}
複製程式碼

AttachJNI函式中主要是建立一個AndroidShellHolder物件,它的建構函式實現如下。

[-> flutter/shell/platform/android/android_shell_holder.cc]

AndroidShellHolder::AndroidShellHolder(
    flutter::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++);
            
  //建立目標執行緒
  if (is_background_view) {
    //僅建立UI執行緒
    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 GPU threads exit.
  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_.gpu_thread->GetTaskRunner()->PostTask(jni_exit_task);
  }

  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;
        //建立PlatformViewAndroid物件
        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::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
    //建立刪格化器
    return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
  };

  //將當前執行緒(Android主執行緒)作為平臺執行緒(platform thread)並確保已經初始化Message Loop
  fml::MessageLoop::EnsureInitializedForCurrentThread();
  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_.gpu_thread->GetTaskRunner();
    ui_runner = thread_host_.ui_thread->GetTaskRunner();
    io_runner = thread_host_.io_thread->GetTaskRunner();
  }
  //建立TaskRunners物件
  flutter::TaskRunners task_runners(thread_label,     // label
                                    platform_runner,  // platform
                                    gpu_runner,       // gpu
                                    ui_runner,        // ui
                                    io_runner         // io
  );

  //建立Shell物件
  shell_ =
      Shell::Create(task_runners,             // task runners
                    GetDefaultWindowData(),   // 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;

  if (is_valid_) {
    //降低GPU執行緒的優先順序
    task_runners.GetGPUTaskRunner()->PostTask([]() {
      //Android將-8描述為“最重要的顯示執行緒,用於合成螢幕和檢索輸入事件”。 保守地將GPU執行緒設定為比其優先順序稍低的優先順序。
      //將GPU執行緒優先順序設為-5。
      if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
        //如果無法將GPU執行緒優先順序設為-5,那麼繼續將GPU執行緒優先順序設為-2。
        if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
          FML_LOG(ERROR) << "Failed to set GPU task runner priority";
        }
      }
    });
    //將UI執行緒優先順序設為-1。
    task_runners.GetUITaskRunner()->PostTask([]() {
      if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
        FML_LOG(ERROR) << "Failed to set UI task runner priority";
      }
    });
  }
}
複製程式碼

上面程式碼還是比較多的,但主要做了以下幾件事。

  1. 目標執行緒的建立,如果is_background_view為true,則僅會建立UI執行緒,否則會建立UI、GPU及IO執行緒。is_background_view預設為false。
  2. 將當前執行緒(Android主執行緒)作為平臺執行緒(platform thread)並確保已經初始化Message Loop。
  3. Shell物件的建立。
  4. GPU執行緒及UI執行緒優先順序的修改。

從上面可以得出Android主執行緒(UI執行緒)是作為Flutter的平臺執行緒(platform thread)存在的,與Flutter的UI執行緒不是同一執行緒,所以不要將Android的主執行緒(UI執行緒)與Flutter的UI執行緒搞混。

再來看Shell物件的建立。

[-> flutter/shell/common/shell.cc]

std::unique_ptr<Shell> Shell::Create(
    TaskRunners task_runners,
    const WindowData window_data,
    Settings settings,
    Shell::CreateCallback<PlatformView> on_create_platform_view,
    Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
  PerformInitializationTasks(settings);
  PersistentCache::SetCacheSkSL(settings.cache_sksl);
  //Dart虛擬機器的建立
  auto vm = DartVMRef::Create(settings);
  auto vm_data = vm->GetVMData();

  return Shell::Create(std::move(task_runners),        //
                       std::move(window_data),         //
                       std::move(settings),            //
                       vm_data->GetIsolateSnapshot(),  // isolate snapshot
                       on_create_platform_view,        //
                       on_create_rasterizer,           //
                       std::move(vm)                   //
  );
}

複製程式碼

Create函式中,會進行Dart VM的建立,由於Dart VM的建立過程比較複雜,這裡就不過多敘述,後面再一一講解。

再來看Create函式,在該函式中會呼叫CreateShellOnPlatformThread函式,顧名思義,CreateShellOnPlatformThread函式就是在平臺執行緒中建立Shell物件。

[-> flutter/shell/common/shell.cc]

std::unique_ptr<Shell> Shell::Create(
    TaskRunners task_runners,
    const WindowData window_data,
    Settings settings,
    fml::RefPtr<const DartSnapshot> isolate_snapshot,
    const Shell::CreateCallback<PlatformView>& on_create_platform_view,
    const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
    DartVMRef vm) {
  ...

  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),          //
                         window_data,                                     //
                         settings,                                        //
                         isolate_snapshot = std::move(isolate_snapshot),  //
                         on_create_platform_view,                         //
                         on_create_rasterizer                             //
  ]() mutable {
        //在平臺執行緒中建立Shell物件
        shell = CreateShellOnPlatformThread(std::move(vm),
                                            std::move(task_runners),      //
                                            window_data,                  //
                                            settings,                     //
                                            std::move(isolate_snapshot),  //
                                            on_create_platform_view,      //
                                            on_create_rasterizer          //
        );
        //鎖喚醒
        latch.Signal();
      }));
  //鎖等待
  latch.Wait();
  return shell;
}


std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
    DartVMRef vm,
    TaskRunners task_runners,
    const WindowData window_data,
    Settings settings,
    fml::RefPtr<const DartSnapshot> isolate_snapshot,
    const Shell::CreateCallback<PlatformView>& on_create_platform_view,
    const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) {
  ...
  
  //建立Shell物件
  auto shell =
      std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));

  //在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.GetGPUTaskRunner(), [&rasterizer_promise,  //
                                        &snapshot_delegate_promise,
                                        on_create_rasterizer,  //
                                        shell = shell.get()    //
  ]() {
        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)也就是Android主執行緒中建立platform view
  auto platform_view = on_create_platform_view(*shell.get());
  if (!platform_view || !platform_view->GetWeakPtr()) {
    return nullptr;
  }

  //由platform view建立vsync waiter,
  auto vsync_waiter = platform_view->CreateVSyncWaiter();
  if (!vsync_waiter) {
    return nullptr;
  }

  //在IO執行緒上建立IO manager。 必須先初始化IO manager,因為它具有其他子系統依賴的狀態。 必須首先引導它,並獲取必要的引用以初始化其他子系統。
  std::promise<std::unique_ptr<ShellIOManager>> io_manager_promise;
  auto io_manager_future = io_manager_promise.get_future();
  std::promise<fml::WeakPtr<ShellIOManager>> weak_io_manager_promise;
  auto weak_io_manager_future = weak_io_manager_promise.get_future();
  std::promise<fml::RefPtr<SkiaUnrefQueue>> unref_queue_promise;
  auto unref_queue_future = unref_queue_promise.get_future();
  auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner();

  // TODO(gw280): The WeakPtr here asserts that we are derefing it on the
  // same thread as it was created on. We are currently on the IO thread
  // inside this lambda but we need to deref the PlatformView, which was
  // constructed on the platform thread.
  //
  // https://github.com/flutter/flutter/issues/42948
  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()  //
  ]() {
        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();

  //在Flutter的UI執行緒中建立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,                               //
                         &window_data,                                    //
                         isolate_snapshot = std::move(isolate_snapshot),  //
                         vsync_waiter = std::move(vsync_waiter),          //
                         &weak_io_manager_future,                         //
                         &snapshot_delegate_future,                       //
                         &unref_queue_future                              //
  ]() mutable {
        const auto& task_runners = shell->GetTaskRunners();

        //在UI執行緒建立animator,這裡主要是為了將平臺的vsync訊號同步給animator
        auto animator = std::make_unique<Animator>(*shell, task_runners,
                                                   std::move(vsync_waiter));
        //Engine物件的建立,此時已經切換到Flutter的UI執行緒
        engine_promise.set_value(std::make_unique<Engine>(
            *shell,                         //
            dispatcher_maker,               //
            *shell->GetDartVM(),            //
            std::move(isolate_snapshot),    //
            task_runners,                   //
            window_data,                    //
            shell->GetSettings(),           //
            std::move(animator),            //
            weak_io_manager_future.get(),   //
            unref_queue_future.get(),       //
            snapshot_delegate_future.get()  //
            ));
      }));
      
  //啟動Shell
  if (!shell->Setup(std::move(platform_view),  //
                    engine_future.get(),       //
                    rasterizer_future.get(),   //
                    io_manager_future.get())   //
  ) {
    return nullptr;
  }

  return shell;
}
複製程式碼

CreateShellOnPlatformThread函式的實現還是蠻複雜的,但主要還是做了以下幾件事。

  • 在平臺執行緒中建立一個Shell物件。
  • 在GPU執行緒建立刪格化器,Flutter在繪製完成後,會將資料給它進行刪格化處理。關於Flutter的繪製原理可以參考Flutter的繪製流程簡述這篇文章。
  • 在平臺執行緒中建立一個PlatformViewAndroid物件。如果is_background_view為true,會建立一個具備渲染能力的PlatformViewAndroid物件,否則建立的是一個不具備渲染能力且在後臺執行的PlatformViewAndroid物件。
  • 通過PlatformView來建立vsync waiter,主要用於VSYNC訊號的同步。
  • 在IO執行緒建立IO manager。
  • 在Flutter的UI執行緒建立Engine物件。
  • 在平臺執行緒啟動Shell,呼叫Shell物件的Setup函式。

這裡先忽略其他,主要來看Engine物件的建立。在其建構函式中,會建立一個RuntimeController物件。

Engine::Engine(Delegate& delegate,
               const PointerDataDispatcherMaker& dispatcher_maker,
               DartVM& vm,
               fml::RefPtr<const DartSnapshot> isolate_snapshot,
               TaskRunners task_runners,
               const WindowData window_data,
               Settings settings,
               std::unique_ptr<Animator> animator,
               fml::WeakPtr<IOManager> io_manager,
               fml::RefPtr<SkiaUnrefQueue> unref_queue,
               fml::WeakPtr<SnapshotDelegate> snapshot_delegate)
    : delegate_(delegate),
      settings_(std::move(settings)),
      animator_(std::move(animator)),
      activity_running_(true),
      have_surface_(false),
      image_decoder_(task_runners,
                     vm.GetConcurrentWorkerTaskRunner(),
                     io_manager),
      task_runners_(std::move(task_runners)),
      weak_factory_(this) {
  //RuntimeController物件的建立
  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),
      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
      window_data,                           // window data
      settings_.isolate_create_callback,     // isolate create callback
      settings_.isolate_shutdown_callback,   // isolate shutdown callback
      settings_.persistent_isolate_data      // persistent isolate data
  );

  pointer_data_dispatcher_ = dispatcher_maker(*this);
}
複製程式碼

這裡的RuntimeController是一個非常重要的物件,在後面很多地方都會用到它。由於篇幅原因,先來看一下從FlutterActivityRuntimeController物件建立的流程圖。

Flutter之引擎啟動流程

2.1、RootIsolate物件的建立

再來看RuntimeController物件的建立。

RuntimeController::RuntimeController(
    RuntimeDelegate& p_client,
    DartVM* p_vm,
    fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
    TaskRunners p_task_runners,
    fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate,
    fml::WeakPtr<IOManager> p_io_manager,
    fml::RefPtr<SkiaUnrefQueue> p_unref_queue,
    fml::WeakPtr<ImageDecoder> p_image_decoder,
    std::string p_advisory_script_uri,
    std::string p_advisory_script_entrypoint,
    const std::function<void(int64_t)>& idle_notification_callback,
    const WindowData& p_window_data,
    const fml::closure& p_isolate_create_callback,
    const fml::closure& p_isolate_shutdown_callback,
    std::shared_ptr<const fml::Mapping> p_persistent_isolate_data)
    : client_(p_client),
      vm_(p_vm),
      isolate_snapshot_(std::move(p_isolate_snapshot)),
      task_runners_(p_task_runners),
      snapshot_delegate_(p_snapshot_delegate),
      io_manager_(p_io_manager),
      unref_queue_(p_unref_queue),
      image_decoder_(p_image_decoder),
      advisory_script_uri_(p_advisory_script_uri),
      advisory_script_entrypoint_(p_advisory_script_entrypoint),
      idle_notification_callback_(idle_notification_callback),
      window_data_(std::move(p_window_data)),
      isolate_create_callback_(p_isolate_create_callback),
      isolate_shutdown_callback_(p_isolate_shutdown_callback),
      persistent_isolate_data_(std::move(p_persistent_isolate_data)) {
  //建立RootIsolate
  auto strong_root_isolate =
      DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(),  //
                                     isolate_snapshot_,                //
                                     task_runners_,                    //
                                     std::make_unique<Window>(this),   //
                                     snapshot_delegate_,               //
                                     io_manager_,                      //
                                     unref_queue_,                     //
                                     image_decoder_,                   //
                                     p_advisory_script_uri,            //
                                     p_advisory_script_entrypoint,     //
                                     nullptr,                          //
                                     isolate_create_callback_,         //
                                     isolate_shutdown_callback_        //
                                     )
          .lock();

  ...
}
複製程式碼

在建構函式中,會呼叫CreateRootIsolate函式來建立一個isolate作為根Isolate

std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
    const Settings& settings,
    fml::RefPtr<const DartSnapshot> isolate_snapshot,
    TaskRunners task_runners,
    std::unique_ptr<Window> window,
    fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
    fml::WeakPtr<IOManager> io_manager,
    fml::RefPtr<SkiaUnrefQueue> unref_queue,
    fml::WeakPtr<ImageDecoder> image_decoder,
    std::string advisory_script_uri,
    std::string advisory_script_entrypoint,
    Dart_IsolateFlags* flags,
    const fml::closure& isolate_create_callback,
    const fml::closure& isolate_shutdown_callback) {

  ...
  //建立isolate物件
  Dart_Isolate vm_isolate =
      CreateDartIsolateGroup(std::move(isolate_group_data),
                             std::move(isolate_data), flags, error.error());

  ...

  std::shared_ptr<DartIsolate>* root_isolate_data =
      static_cast<std::shared_ptr<DartIsolate>*>(Dart_IsolateData(vm_isolate));

  (*root_isolate_data)->SetWindow(std::move(window));

  return (*root_isolate_data)->GetWeakIsolatePtr();
}
複製程式碼

再來看CreateDartIsolateGroup函式,該函式主要做了兩件事。

  • 通過Dart VM來建立isolate物件,並將該isolate物件作為root isolate。
  • 初始化isolate物件。
Dart_Isolate DartIsolate::CreateDartIsolateGroup(
    std::unique_ptr<std::shared_ptr<DartIsolateGroupData>> isolate_group_data,
    std::unique_ptr<std::shared_ptr<DartIsolate>> isolate_data,
    Dart_IsolateFlags* flags,
    char** error) {

  //通過Dart VM建立一個isolate物件
  Dart_Isolate isolate = Dart_CreateIsolateGroup(
      (*isolate_group_data)->GetAdvisoryScriptURI().c_str(),
      (*isolate_group_data)->GetAdvisoryScriptEntrypoint().c_str(),
      (*isolate_group_data)->GetIsolateSnapshot()->GetDataMapping(),
      (*isolate_group_data)->GetIsolateSnapshot()->GetInstructionsMapping(),
      flags, isolate_group_data.get(), isolate_data.get(), error);

  if (isolate == nullptr) {
    return nullptr;
  }

  // Ownership of the isolate data objects has been transferred to the Dart VM.
  std::shared_ptr<DartIsolate> embedder_isolate(*isolate_data);
  isolate_group_data.release();
  isolate_data.release();
  
  //初始化isolate物件
  if (!InitializeIsolate(std::move(embedder_isolate), isolate, error)) {
    return nullptr;
  }

  return isolate;
}
複製程式碼

先來看Dart_CreateIsolateGroup函式在Dart VM的實現,在其實現函式中會建立isolate物件。

Dart_CreateIsolateGroup(const char* script_uri,
                        const char* name,
                        const uint8_t* snapshot_data,
                        const uint8_t* snapshot_instructions,
                        Dart_IsolateFlags* flags,
                        void* isolate_group_data,
                        void* isolate_data,
                        char** error) {

  Dart_IsolateFlags api_flags;
  if (flags == nullptr) {
    Isolate::FlagsInitialize(&api_flags);
    flags = &api_flags;
  }

  const char* non_null_name = name == nullptr ? "isolate" : name;
  std::unique_ptr<IsolateGroupSource> source(
      new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
                             snapshot_instructions, nullptr, -1, *flags));
  auto group = new IsolateGroup(std::move(source), isolate_group_data);
  IsolateGroup::RegisterIsolateGroup(group);
  Dart_Isolate isolate =
      CreateIsolate(group, non_null_name, isolate_data, error);
  if (isolate != nullptr) {
    group->set_initial_spawn_successful();
  }
  return isolate;
}
複製程式碼

CreateIsolate函式就會建立一個isolate物件,關於後續的isolate物件的建立及isolate的更多內容可以去閱讀深入理解Isolate這篇文章。

再來看isolate物件的初始化函式——InitializeIsolate的實現。

bool DartIsolate::InitializeIsolate(
    std::shared_ptr<DartIsolate> embedder_isolate,
    Dart_Isolate isolate,
    char** error) {
  if (!embedder_isolate->Initialize(isolate)) {//初始化
    *error = fml::strdup("Embedder could not initialize the Dart isolate.");
9999    return false;
  } 
  
  //isolate載入library
  if (!embedder_isolate->LoadLibraries()) {
    *error = fml::strdup(
        "Embedder could not load libraries in the new Dart isolate.");
    return false;
  }

  // Root isolates will be setup by the engine and the service isolate (which is
  // also a root isolate) by the utility routines in the VM. However, secondary
  // isolates will be run by the VM if they are marked as runnable.
  if (!embedder_isolate->IsRootIsolate()) {
    auto child_isolate_preparer =
        embedder_isolate->GetIsolateGroupData().GetChildIsolatePreparer();
    if (!child_isolate_preparer(embedder_isolate.get())) {
      *error = fml::strdup("Could not prepare the child isolate to run.");
      return false;
    }
  }

  return true;
}

//初始化
bool DartIsolate::Initialize(Dart_Isolate dart_isolate) {
  if (phase_ != Phase::Uninitialized) {
    return false;
  }

  if (dart_isolate == nullptr) {
    return false;
  }

  if (Dart_CurrentIsolate() != dart_isolate) {
    return false;
  }

  //從這裡開始,可以安全的使用isolate
  SetIsolate(dart_isolate);

  // We are entering a new scope (for the first time since initialization) and
  // we want to restore the current scope to null when we exit out of this
  // method. This balances the implicit Dart_EnterIsolate call made by
  // Dart_CreateIsolateGroup (which calls the Initialize).
  Dart_ExitIsolate();

  tonic::DartIsolateScope scope(isolate());

  //設定UI執行緒的訊息處理器
  SetMessageHandlingTaskRunner(GetTaskRunners().GetUITaskRunner());

  if (tonic::LogIfError(
          Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))) {
    return false;
  }

  if (!UpdateThreadPoolNames()) {
    return false;
  }
  //初始化完成
  phase_ = Phase::Initialized;
  return true;
}

void DartIsolate::SetMessageHandlingTaskRunner(
    fml::RefPtr<fml::TaskRunner> runner) {
  if (!IsRootIsolate() || !runner) {
    return;
  }

  message_handling_task_runner_ = runner;
  
  //設定訊息處理器
  message_handler().Initialize(
      [runner](std::function<void()> task) { runner->PostTask(task); });
}
複製程式碼

最終在SetMessageHandlingTaskRunner函式中將UITaskRunner設定為Flutter中UI執行緒的訊息處理器,進行UI執行緒中訊息的分發並處理。也就是說在RootIsolate中,訊息並不是通過執行緒池中來分發及處理的,所以不要在UI執行緒的訊息中進行耗時操作,否則影響UI繪製。其實在Android平臺上的Flutter的訊息處理機制與Android中的訊息機制類似,都是使用的Android平臺的Looper。更多內容後面再來一一講解。

void DartMessageHandler::Initialize(TaskDispatcher dispatcher) {
  // Only can be called once.
  TONIC_CHECK(!task_dispatcher_ && dispatcher);
  task_dispatcher_ = dispatcher;
  Dart_SetMessageNotifyCallback(MessageNotifyCallback);
}
複製程式碼

Dart_SetMessageNotifyCallback中其實就是給RootIsolate設定訊息通知回撥,程式碼如下。

DART_EXPORT void Dart_SetMessageNotifyCallback(
    Dart_MessageNotifyCallback message_notify_callback) {
  Isolate* isolate = Isolate::Current();
  CHECK_ISOLATE(isolate);

  {
    NoSafepointScope no_safepoint_scope;
    isolate->set_message_notify_callback(message_notify_callback);
  }

  if (message_notify_callback != nullptr && isolate->HasPendingMessages()) {
    ::Dart_ExitIsolate();

    // If a new handler gets installed and there are pending messages in the
    // queue (e.g. OOB messages for doing vm service work) we need to notify
    // the newly registered callback, otherwise the embedder might never get
    // notified about the pending messages.
    message_notify_callback(Api::CastIsolate(isolate));

    ::Dart_EnterIsolate(Api::CastIsolate(isolate));
  }
}
複製程式碼

關於RootIsolate的相關呼叫流程圖如下。

Flutter之引擎啟動流程
到此,一個Engine物件就已經建立完畢。再回到Shell中,來看ShellSetup函式是如何啟動的。程式碼如下。

bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
                  std::unique_ptr<Engine> engine,
                  std::unique_ptr<Rasterizer> rasterizer,
                  std::unique_ptr<ShellIOManager> io_manager) {
  if (is_setup_) {
    return false;
  }

  //platform_view、engine、rasterizer及io_manager只要有一個建立失敗,Shell啟動就會失敗
  if (!platform_view || !engine || !rasterizer || !io_manager) {
    return false;
  }

  platform_view_ = std::move(platform_view);
  engine_ = std::move(engine);
  rasterizer_ = std::move(rasterizer);
  io_manager_ = std::move(io_manager);

  // The weak ptr must be generated in the platform thread which owns the unique
  // ptr.
  weak_engine_ = engine_->GetWeakPtr();
  weak_rasterizer_ = rasterizer_->GetWeakPtr();
  weak_platform_view_ = platform_view_->GetWeakPtr();

  is_setup_ = true;

  vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription());

  PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner(
      task_runners_.GetIOTaskRunner());

  PersistentCache::GetCacheForProcess()->SetIsDumpingSkp(
      settings_.dump_skp_on_shader_compilation);

  // TODO(gw280): The WeakPtr here asserts that we are derefing it on the
  // same thread as it was created on. Shell is constructed on the platform
  // thread but we need to call into the Engine on the UI thread, so we need
  // to use getUnsafe() here to avoid failing the assertion.
  //
  // https://github.com/flutter/flutter/issues/42947
  display_refresh_rate_ = weak_engine_.getUnsafe()->GetDisplayRefreshRate();

  return true;
}
複製程式碼

Setup函式中主要是檢查Shell的子元件是否已經初始化,如Engineplatform_viewrasterizerio manager等,然後將這些元件設定為全域性。

如果該函式返回true就表示引擎已經建立成功。

3、Engine的執行

再回到類FlutterActivityDelegate中,當引擎建立完畢後,再呼叫runBundle方法來執行Flutter程式碼。

public final class FlutterActivityDelegate
        implements FlutterActivityEvents,
                   FlutterView.Provider,
                   PluginRegistry {
    private void runBundle(String appBundlePath) {
        if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
            FlutterRunArguments args = new FlutterRunArguments();
            //flutter程式碼路徑
            args.bundlePath = appBundlePath;
            //flutter入口函式
            args.entrypoint = "main";
            flutterView.runFromBundle(args);
        }
    }
}
複製程式碼

先來看FlutterRunArguments,它僅有三個欄位,如下。

public class FlutterRunArguments {
  public String bundlePath;
  public String entrypoint;
  public String libraryPath;
}
複製程式碼

runBundle方法中呼叫FlutterViewrunFromBundle方法時,欄位libraryPath為空。在後面會用到根據entrypointlibraryPath有不同實現。

public class FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry {
    public void runFromBundle(FlutterRunArguments args) {
      assertAttached();
      preRun();
      //執行flutter程式碼
      mNativeView.runFromBundle(args);
      postRun();
    }
}
public class FlutterNativeView implements BinaryMessenger {
    public void runFromBundle(FlutterRunArguments args) {
        if (args.entrypoint == null) {
            throw new AssertionError("An entrypoint must be specified");
        }
        assertAttached();
        if (applicationIsRunning)
            throw new AssertionError(
                    "This Flutter engine instance is already running an application");
        mFlutterJNI.runBundleAndSnapshotFromLibrary(
            args.bundlePath,
            args.entrypoint,
            args.libraryPath,
            mContext.getResources().getAssets()
        );

        applicationIsRunning = true;
    }
}
public class FlutterJNI {
  @UiThread
  public void runBundleAndSnapshotFromLibrary(
      @NonNull String bundlePath,
      @Nullable String entrypointFunctionName,
      @Nullable String pathToEntrypointFunction,
      @NonNull AssetManager assetManager
  ) {
    ensureRunningOnMainThread();
    ensureAttachedToNative();
    nativeRunBundleAndSnapshotFromLibrary(
        nativePlatformViewId,
        bundlePath,
        entrypointFunctionName,
        pathToEntrypointFunction,
        assetManager
    );
  }

  private native void nativeRunBundleAndSnapshotFromLibrary(
      long nativePlatformViewId,
      @NonNull String bundlePath,
      @Nullable String entrypointFunctionName,
      @Nullable String pathToEntrypointFunction,
      @NonNull AssetManager manager
  );
}
複製程式碼

nativeRunBundleAndSnapshotFromLibrary又是一個native方法,它在引擎中對應的函式實現如下。

static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
                                            jobject jcaller,
                                            jlong shell_holder,
                                            jstring jBundlePath,
                                            jstring jEntrypoint,
                                            jstring jLibraryUrl,
                                            jobject jAssetManager) {
  ...
  
  //根據配置檔案來啟動引擎
  ANDROID_SHELL_HOLDER->Launch(std::move(config));
}
複製程式碼

RunBundleAndSnapshotFromLibrary主要是對傳遞的引數進行封裝,然後呼叫ShellLaunch函式來執行引擎。

void AndroidShellHolder::Launch(RunConfiguration config) {
  if (!IsValid()) {
    return;
  }
  
  //根據配置執行引擎
  shell_->RunEngine(std::move(config));
}

複製程式碼

RunEngine函式的程式碼實現如下。

void Shell::RunEngine(RunConfiguration run_configuration) {
  RunEngine(std::move(run_configuration), nullptr);
}

void Shell::RunEngine(
    RunConfiguration run_configuration,
    const std::function<void(Engine::RunStatus)>& result_callback) {
  auto result = [platform_runner = task_runners_.GetPlatformTaskRunner(),
                 result_callback](Engine::RunStatus run_result) {
    if (!result_callback) {
      return;
    }
    platform_runner->PostTask(
        [result_callback, run_result]() { result_callback(run_result); });
  };
  //在Flutter的UI執行緒呼叫Engine物件的run函式
  fml::TaskRunner::RunNowOrPostTask(
      task_runners_.GetUITaskRunner(),
      fml::MakeCopyable(
          [run_configuration = std::move(run_configuration),
           weak_engine = weak_engine_, result]() mutable {
            if (!weak_engine) {
              result(Engine::RunStatus::Failure);
              return;
            }
            //weak_engine是在執行shell的Setup函式時設定的。
            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);
          }));
}
複製程式碼

通過執行Engine物件的Run函式,就可以讓Engine物件跑起來,實現程式碼如下。

Engine::RunStatus Engine::Run(RunConfiguration configuration) {
  if (!configuration.IsValid()) {
    return RunStatus::Failure;
  }

  last_entry_point_ = configuration.GetEntrypoint();
  last_entry_point_library_ = configuration.GetEntrypointLibrary();
  
  //準備並啟動Isolate
  auto isolate_launch_status =
      PrepareAndLaunchIsolate(std::move(configuration));
      
  ...

  return isolate_running ? Engine::RunStatus::Success
                         : Engine::RunStatus::Failure;
}
複製程式碼

下面再來看PrepareAndLaunchIsolate函式的實現。

Engine::RunStatus Engine::PrepareAndLaunchIsolate(
    RunConfiguration configuration) {

  ...

  //預設情況下,configuration.GetEntrypointLibrary()為空
  if (configuration.GetEntrypointLibrary().empty()) {
    //執行isolate
    if (!isolate->Run(configuration.GetEntrypoint(),
                      settings_.dart_entrypoint_args)) {
      FML_LOG(ERROR) << "Could not run the isolate.";
      return RunStatus::Failure;
    }
  } else {
    if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(),
                                 configuration.GetEntrypoint(),
                                 settings_.dart_entrypoint_args)) {
      FML_LOG(ERROR) << "Could not run the isolate.";
      return RunStatus::Failure;
    }
  }

  return RunStatus::Success;
}
複製程式碼

預設情況下,configuration.GetEntrypointLibrary()返回值為空,所以這裡會呼叫DartIsolaterun函式來執行isolate

bool DartIsolate::Run(const std::string& entrypoint_name,
                      const std::vector<std::string>& args,
                      const fml::closure& on_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()));

  auto entrypoint_args = tonic::ToDart(args);
  //呼叫main方法
  if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
    return false;
  }

  phase_ = Phase::Running;

  if (on_run) {
    on_run();
  }
  return true;
}
複製程式碼

InvokeMainEntrypoint顧名思義就是呼叫Flutter專案中的入口函式——main方法。

static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function,
                                 Dart_Handle args) {
  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, args}))) {
    FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
    return false;
  }

  return true;
}
複製程式碼

來看_getStartMainIsolateFunction函式的實現,它返回了一個_startMainIsolate函式。

@pragma("vm:entry-point", "call")
Function _getStartMainIsolateFunction() {
  return _startMainIsolate;
}
@pragma("vm:entry-point", "call")
void _startMainIsolate(Function entryPoint, List<String> args) {
  _startIsolate(
      null, // no parent port
      entryPoint,
      args,
      null, // no message
      true, // isSpawnUri
      null, // no control port
      null); // no capabilities
}
複製程式碼

再來看_runMainZoned函式的實現,它就直接執行_getStartMainIsolateFunction函式的返回函式_startMainIsolate

@pragma('vm:entry-point')
// ignore: unused_element
void _runMainZoned(Function startMainIsolateFunction,
                   Function userMainFunction,
                   List<String> args) {
  startMainIsolateFunction((){
    runZoned<void>(() {
      if (userMainFunction is _BinaryFunction) {
        // This seems to be undocumented but supported by the command line VM.
        // Let's do the same in case old entry-points are ported to Flutter.
        (userMainFunction as dynamic)(args, '');
      } else if (userMainFunction is _UnaryFunction) {
        (userMainFunction as dynamic)(args);
      } else {
        userMainFunction();
      }
    }, onError: (Object error, StackTrace stackTrace) {
      _reportUnhandledException(error.toString(), stackTrace.toString());
    });
  }, null);
}
複製程式碼

_startMainIsolate函式中就是直接執行RootIsolate並執行入口函式。

@pragma("vm:entry-point", "call")
void _startIsolate(
    SendPort parentPort,
    Function entryPoint,
    List<String> args,
    var message,
    bool isSpawnUri,
    RawReceivePort controlPort,
    List capabilities) {
  ...

  //將所有使用者程式碼處理延遲到訊息迴圈的下一次執行。 這使我們能夠攔截事件分發中的某些條件,例如從暫停狀態開始。
  RawReceivePort port = new RawReceivePort();
  port.handler = (_) {
    port.close();

    if (isSpawnUri) {
      if (entryPoint is _BinaryFunction) {
        (entryPoint as dynamic)(args, message);
      } else if (entryPoint is _UnaryFunction) {
        (entryPoint as dynamic)(args);
      } else {
        entryPoint();
      }
    } else {
      entryPoint(message);
    }
  };
  //確保訊息處理程式已觸發。
  port.sendPort.send(null);
}
複製程式碼

_startIsolate方法中,就會執行Flutter中的入口函式,如下。

void main() => runApp(MyApp());
複製程式碼

執行Flutter程式碼的流程圖如下。

Flutter之引擎啟動流程

4、總結

由於東西比較多,所以本文只是描述了引擎的整體建立流程,一些細節也沒有具體講述。但如果熟悉了引擎的建立流程,那麼也就能很快的去了解細節的具體實現。

【參考資料】

深入理解Flutter引擎啟動

相關文章