Flutter启动流程源码分析

Flutter启动流程源码分析

Flutter的启动从java代码层面上看是离不开FlutterApplicationFlutterActivity这两个类的,下面我们就以flutter1.12.13版本为例来看下源码

一、FlutterApplication启动流程

1.1、FlutterApplication.onCreate

public void onCreate() {
    super.onCreate();
  // 初始化flutter相关资源
    FlutterMain.startInitialization(this);
}

1.2、FlutterMain

Flutter engine初始化类

public static void startInitialization(@NonNull Context applicationContext) {
  if (isRunningInRobolectricTest) {
    return;
  }
  // 从1.9.1+hotfix.6时单独抽出了一个单例FlutterLoader
  FlutterLoader.getInstance().startInitialization(applicationContext);
}

1.3、FlutterLoader

在apk中查找flutter resources并加载libflutter.so

FlutterLoader-->startInitialization

public void startInitialization(@NonNull Context applicationContext) {
  // 初始化一个默认的Setting
  startInitialization(applicationContext, new Settings());
}
public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
  // 首次执行时全局的settings还未被赋值,保证startInitialization只执行一次
  if (this.settings != null) {
    return;
  }
  // 保证在主线程中执行初始化操作
  if (Looper.myLooper() != Looper.getMainLooper()) {
    throw new IllegalStateException("startInitialization must be called on the main thread");
  }

  // 使用application的context.
  applicationContext = applicationContext.getApplicationContext();
    // 给全局的settings赋值
  this.settings = settings;

  long initStartTimestampMillis = SystemClock.uptimeMillis();
  // 初始化配置
  initConfig(applicationContext);
  // 初始化资源加载
  initResources(applicationContext);
    // 这个类的主要作用之一:加载libflutter.so
  System.loadLibrary("flutter");

  VsyncWaiter.getInstance(
    (WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE))
    .init();

  long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
  // 调用C层代码记录一下application启动的时间
  FlutterJNI.nativeRecordStartTimestamp(initTimeMillis);
}

FlutterLoader-->initConfig

加载androidManifest.xml中的flutter相关的配置:

1、aot模式时libapp.so库的位置(默认在lib/armeabi-v7a或者lib/arm64-v8a文件夹下)

2、flutter_assets资源文件的路径(默认在assets文件夹下)

3、JIT模式时vm_snapshot_data的位置(默认在debug时在flutter_assets文件夹下)

4、JIT模式时isolate_snapshot_data的位置(默认在debug时在flutter_assets文件夹下)

private void initConfig(@NonNull Context applicationContext) {
  Bundle metadata = getApplicationInfo(applicationContext).metaData;

  // There isn't a `` tag as a direct child of `` in
  // `AndroidManifest.xml`.
  if (metadata == null) {
    return;
  }

  aotSharedLibraryName =
    metadata.getString(PUBLIC_AOT_SHARED_LIBRARY_NAME, DEFAULT_AOT_SHARED_LIBRARY_NAME);
  flutterAssetsDir =
    metadata.getString(PUBLIC_FLUTTER_ASSETS_DIR_KEY, DEFAULT_FLUTTER_ASSETS_DIR);

  vmSnapshotData = metadata.getString(PUBLIC_VM_SNAPSHOT_DATA_KEY, DEFAULT_VM_SNAPSHOT_DATA);
  isolateSnapshotData =
    metadata.getString(PUBLIC_ISOLATE_SNAPSHOT_DATA_KEY, DEFAULT_ISOLATE_SNAPSHOT_DATA);
}

FlutterLoader.initResources

在debug或者JIT模式下,加载vm_snapshot_data、isolate_snapshot_data、kernel_blob.bin

private void initResources(@NonNull Context applicationContext) {
  // 先清空data/user/0/package/cache目录下文件
  new ResourceCleaner(applicationContext).start();
    // debug或者JIT模式
  if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
    // data/user/0/package/app_flutter目录
    final String dataDirPath = PathUtils.getDataDirectory(applicationContext);
    final String packageName = applicationContext.getPackageName();
    final PackageManager packageManager = applicationContext.getPackageManager();
    final AssetManager assetManager = applicationContext.getResources().getAssets();
    resourceExtractor =
      new ResourceExtractor(dataDirPath, packageName, packageManager, assetManager);
    
    // 资源加载到列表中
    resourceExtractor
      .addResource(fullAssetPathFrom(vmSnapshotData)) // fullAssetPathFrom是拼写flutter_assets全路径的方法
      .addResource(fullAssetPathFrom(isolateSnapshotData))
      .addResource(fullAssetPathFrom(DEFAULT_KERNEL_BLOB));
    
    // 启动一个AsyncTask任务,会将data/user/0/package/app_flutter目录下对应的vm_snapshot_data、isolate_snapshot_data、kernel_blob.bin的文件先删除,然后从apk安装目录的assets中复制新的文件使用
    resourceExtractor.start();
  }
}

1.4、FlutterJNI

调用libflutter.so时用到的JNI方法封装

// 记录application启动的时间
public static native void nativeRecordStartTimestamp(long initTimeMillis);

1.5、flutter_main.cc

主要是定义了两个方法:nativeInit、nativeRecordStartTimestamp

bool FlutterMain::Register(JNIEnv* env) {
  static const JNINativeMethod methods[] = {
      // 。。。。。。省略其他代码
      {
            // JNI方法nativeRecordStartTimestamp,转化成调用C++的RecordStartTimestamp方法
          .name = "nativeRecordStartTimestamp",
          .signature = "(J)V",
          .fnPtr = reinterpret_cast(&RecordStartTimestamp),
      },
  };
  // 。。。。。。省略其他代码
}

1.6、libary_loader.cc

在加载libflutter.so时会触发JNI_OnLoad方法

// 注册FlutterMain的JNI方法
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
  // 。。。。。。省略其他代码
    result = flutter::FlutterMain::Register(env);
  // 。。。。。。省略其他代码
}

附FlutterApplication时序图

image-flutter-application.png


image

二、FlutterActivity

在flutter中有两个FlutterActivity,一个是io.flutter.app.FlutterActivity,另一个是io.flutter.embedding.android.FlutterActivity,前者是老版本的Flutter运行相关类,在1.12版本已经不建议使用了。参考文档https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects,下面讲解的都是io.flutter.embedding.android.FlutterActivity。

2.1、FlutterActivity

2.1.1、onCreate
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
  // 查看metedata中是否有配置主题
  switchLaunchThemeForNormalTheme();
  super.onCreate(savedInstanceState);
  lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    // 初始化delegate
  delegate = new FlutterActivityAndFragmentDelegate(this);
  // 初始化flutter engine相关
  delegate.onAttach(this);
  // 为插件提供恢复状态的onRestoreInstanceState
  delegate.onActivityCreated(savedInstanceState);

  // 当Intent配置的backgroundMode是透明时,就配置window是否透明
  configureWindowForTransparency();
  // 创建FlutterView
  setContentView(createFlutterView());
  configureStatusBarForFullscreenFlutterExperience();
}
2.1.2、configureWindowForTransparency
public FlutterView.RenderMode getRenderMode() {
    // 获取intent里传递的backgroundMode,opaque表示不透明
    return getBackgroundMode() == BackgroundMode.opaque
        ? FlutterView.RenderMode.surface
        : FlutterView.RenderMode.texture;
}
private void configureWindowForTransparency() {
    BackgroundMode backgroundMode = getBackgroundMode();
    if (backgroundMode == BackgroundMode.transparent) {
      getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
      getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
        WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
      );
    }
  }
2.1.3、createFlutterView
private View createFlutterView() {
    // 通过代理创建flutterView
    return delegate.onCreateView(
    null /* inflater */,
    null /* container */,
    null /* savedInstanceState */);
}

2.2、FlutterActivityAndFragmentDelegate

2.2.1、onAttach

主要做以下几件事:

1、获取或者创建flutter engine

2、创建和配置PlatformPlugin

3、将flutterEngine附加到activity

void onAttach(@NonNull Context context) {
    ensureAlive();

    // 当这个FlutterActivity是复用时,flutter engine复用
    if (flutterEngine == null) {
      setupFlutterEngine();
    }

    // 创建和配置platform plugin
    platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);

    if (host.shouldAttachEngineToActivity()) {
      // 将flutter engine附加到activity
      Log.d(TAG, "Attaching FlutterEngine to the Activity that owns this Fragment.");
      flutterEngine.getActivityControlSurface().attachToActivity(
          host.getActivity(),
          host.getLifecycle()
      );
    }
        // flutter activity配置flutter engine提供入口
    host.configureFlutterEngine(flutterEngine);
  }

2.2.2、onCreateView

View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    Log.v(TAG, "Creating FlutterView.");
    ensureAlive();
    // 创建flutterView
    flutterView = new FlutterView(host.getActivity(), host.getRenderMode(), host.getTransparencyMode());
    flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);
        // 创建一个在view直到flutter的第一帧显示出来
    flutterSplashView = new FlutterSplashView(host.getContext());
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
      flutterSplashView.setId(View.generateViewId());
    } else {
      flutterSplashView.setId(486947586);
    }
    // 当flutter view第一帧渲染后会移除splash view
    flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen());

    return flutterSplashView;
 }

三、FlutterEngine

3.1、构造方法时调用
public FlutterEngine(
      @NonNull Context context,
      @NonNull FlutterLoader flutterLoader,
      @NonNull FlutterJNI flutterJNI,
      @NonNull PlatformViewsController platformViewsController,
      @Nullable String[] dartVmArgs,// FlutterActivity重写getFlutterShellArgs方法可以添加参数
      boolean automaticallyRegisterPlugins) {
    this.flutterJNI = flutterJNI;
    // 初始化配置、资源、加载libflutter.so;如果使用了FlutterApplication,也不会重复初始化操作
    flutterLoader.startInitialization(context.getApplicationContext());
    // 确保初始化完成
    flutterLoader.ensureInitializationComplete(context, dartVmArgs);

    flutterJNI.addEngineLifecycleListener(engineLifecycleListener);
    // 调用flutterJNI的attachToNative初始化setting配置
    attachToJni();

    this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets());
    this.dartExecutor.onAttachedToJNI();

    // 。。。。。省略
  }
3.2、attachToJni
private void attachToJni() {
    Log.v(TAG, "Attaching to JNI.");
    // 通过FlutterJNI调用libflutter.so中的方法
    flutterJNI.attachToNative(false);
    if (!isAttachedToJni()) {
      throw new RuntimeException("FlutterEngine failed to attach to its native Object reference.");
    }
  }

四、FlutterJNI

通过这个类调用flutter engine中的 C/C++ 代码,对应platform_view_android_jni.cc代码

// 将java层初始化的参数传递给C++层
public static native void nativeInit(
      @NonNull Context context,
      @NonNull String[] args,
      @Nullable String bundlePath,
      @NonNull String appStoragePath,
      @NonNull String engineCachesPath);
// 初始化AndroidShellHolder
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);

附上FlutterActivity启动时序图

image

了解完Flutter的启动流程,下一篇文章我们就来配置一下flutter engine的编译环境,以及一步步的实现flutter的动态化,敬请期待

你可能感兴趣的:(Flutter启动流程源码分析)