Flutter Android 端 Activity/Fragment 流程源码分析

Posted 工匠若水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter Android 端 Activity/Fragment 流程源码分析相关的知识,希望对你有一定的参考价值。

Flutter 系列文章连载~
《Flutter Android 工程结构及应用层编译源码深入分析》
《Flutter 命令本质之 Flutter tools 机制源码深入分析》
《Flutter 的 runApp 与三棵树诞生流程源码分析》
《Flutter Android 端 Activity/Fragment 流程源码分析》

背景

前面文章我们分析了 flutter 在 android 端编译命令相关流程,我们接下来需要先分析一下 Flutter Android 端 framework 平台实现代码(非 native engine 引擎部分),下面以一个纯 Flutter App 为例展开分析。

工程结构及 API 变更

对于一个纯 flutter app 来说,当我们在 yaml 依赖中添加两个 flutter plugin 依赖,然后铜过 Android Studio 导入安卓工程后可以看到如下结构:

gradle sync 后对应的安卓依赖如下:

可以看到,上面依赖就是我们《Flutter Android 工程结构及应用层编译源码深入分析》一文中分析 Flutter Android App 编译流程中提到过的动态追加依赖。

对于 Android 平台来说,Flutter 依赖其实蛮简单的,我们以启用 androidx 为例展示 release 模式下的依赖关系,如下:

releaseRuntimeClasspath - Resolved configuration for runtime for variant: release
+--- io.flutter:flutter_embedding_release:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce
|    +--- androidx.lifecycle:lifecycle-common:2.2.0
|    |    \\--- androidx.annotation:annotation:1.1.0
|    +--- androidx.lifecycle:lifecycle-common-java8:2.2.0
|    |    +--- androidx.lifecycle:lifecycle-common:2.2.0 (*)
|    |    \\--- androidx.annotation:annotation:1.1.0
|    +--- androidx.lifecycle:lifecycle-runtime:2.2.0
|    |    +--- androidx.lifecycle:lifecycle-common:2.2.0 (*)
|    |    +--- androidx.arch.core:core-common:2.1.0
|    |    |    \\--- androidx.annotation:annotation:1.1.0
|    |    \\--- androidx.annotation:annotation:1.1.0
|    +--- androidx.fragment:fragment:1.1.0
|    |    +--- androidx.annotation:annotation:1.1.0
|    |    +--- androidx.core:core:1.1.0
|    |    |    +--- androidx.annotation:annotation:1.1.0
|    |    |    +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.2.0 (*)
|    |    |    +--- androidx.versionedparcelable:versionedparcelable:1.1.0
|    |    |    |    \\--- androidx.collection:collection:1.0.0 -> 1.1.0
|    |    |    |         \\--- androidx.annotation:annotation:1.1.0
|    |    |    \\--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|    |    +--- androidx.collection:collection:1.1.0 (*)
|    |    +--- androidx.viewpager:viewpager:1.0.0
|    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|    |    |    +--- androidx.core:core:1.0.0 -> 1.1.0 (*)
|    |    |    \\--- androidx.customview:customview:1.0.0
|    |    |         +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|    |    |         \\--- androidx.core:core:1.0.0 -> 1.1.0 (*)
|    |    +--- androidx.loader:loader:1.0.0
|    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|    |    |    +--- androidx.core:core:1.0.0 -> 1.1.0 (*)
|    |    |    +--- androidx.lifecycle:lifecycle-livedata:2.0.0
|    |    |    |    +--- androidx.arch.core:core-runtime:2.0.0
|    |    |    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|    |    |    |    |    \\--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
|    |    |    |    +--- androidx.lifecycle:lifecycle-livedata-core:2.0.0
|    |    |    |    |    +--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.2.0 (*)
|    |    |    |    |    +--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
|    |    |    |    |    \\--- androidx.arch.core:core-runtime:2.0.0 (*)
|    |    |    |    \\--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
|    |    |    \\--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 -> 2.1.0
|    |    |         \\--- androidx.annotation:annotation:1.1.0
|    |    +--- androidx.activity:activity:1.0.0
|    |    |    +--- androidx.annotation:annotation:1.1.0
|    |    |    +--- androidx.core:core:1.1.0 (*)
|    |    |    +--- androidx.lifecycle:lifecycle-runtime:2.1.0 -> 2.2.0 (*)
|    |    |    +--- androidx.lifecycle:lifecycle-viewmodel:2.1.0 (*)
|    |    |    \\--- androidx.savedstate:savedstate:1.0.0
|    |    |         +--- androidx.annotation:annotation:1.1.0
|    |    |         +--- androidx.arch.core:core-common:2.0.1 -> 2.1.0 (*)
|    |    |         \\--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.2.0 (*)
|    |    \\--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 -> 2.1.0 (*)
|    \\--- androidx.annotation:annotation:1.1.0
+--- io.flutter:armeabi_v7a_release:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce
+--- io.flutter:arm64_v8a_release:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce
\\--- io.flutter:x86_64_release:1.0.0-241c87ad800beeab545ab867354d4683d5bfb6ce

可以看到依赖主要都是 androidx,还是蛮香的。

源码分析

Flutter Android 端源码主要依赖于 gradle maven 下载,也就是上图中的io.flutter:flutter_embedding_XXX代码,另一个 ABI 依赖是libflutter.so引擎依赖。

本文以 Flutter 2.2.3 版本为例分析,由于新旧版本的 Android 入口存在差异,譬如新版本不再默认使用FlutterApplication配合io.flutter.app.FlutterActivity模式,而是直接使用io.flutter.embedding.android.FlutterActivty,所以我们的入口要从新的看起(注意新旧同类名不同包名的区别)。相关新旧版本迁移变更可以参考官方说明的Upgrading-pre-1.12-Android-projects

FlutterActivity 相关分析

Android App 中默认 Flutter UI 界面呈现在平台层的实现都继承自io.flutter.embedding.android.FlutterActivity,主题默认也是一个全屏无 ActionBar 形式,源码如下:

public class FlutterActivity extends Activity
    implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner {
  ......
}

依据这个继承关系可以看到,FlutterActivity 直接继承自 Activity,而不是兼容包的 AppCompatActivity,这对于有历史包袱的 App 来说是一件好事,也秉承了一个优质 SDK 去依赖的优质特点。同时其实现了两个接口,LifecycleOwner 为标准 AAC 框架成员,我们不再解释;重点看下FlutterActivityAndFragmentDelegate.Host,源码如下:

class FlutterActivityAndFragmentDelegate implements ExclusiveAppComponent<Activity> {
  ......
  //这里的一堆extends接口不多解释,注释都很明确
  interface Host
      extends SplashScreenProvider,
          FlutterEngineProvider,
          FlutterEngineConfigurator,
          PlatformPlugin.PlatformPluginDelegate {
    //1、获取宿主Activity或Fragment的context。
    //对应上面FlutterActivity实现此接口就是返回他自己的context,也就是this。
    @NonNull
    Context getContext();
    //2、是否可以通过deeplink调起initial route路由。
    //主要是在AndroidManifest.xml中Activity配置flutter_deeplinking_enabled meta值。
    //参见官方文档 https://flutter.dev/docs/development/ui/navigation/deep-linking
    @Nullable
    boolean shouldHandleDeeplinking();
	//3、获取宿主Activity或Fragment的attached Activity。
    //对应上面FlutterActivity实现此接口就是返回他自己,也就是this。
    @Nullable
    Activity getActivity();
	//4、获取宿主Activity或Fragment的Lifecycle。
    @NonNull
    Lifecycle getLifecycle();
	//5、获取宿主启动Flutter携带的参数,通过intent解析,譬如enable-dart-profiling等。
    @NonNull
    FlutterShellArgs getFlutterShellArgs();
	//6、获取静态缓存的EngineId,如果没有就返回空,通过intent的cached_engine_id参数传递。
    @Nullable
    String getCachedEngineId();
    //7、当FlutterActivity destory后是否销毁引擎实例,默认要销毁。
    //当FlutterEngine属于Activity自己则需要销毁返回true,当FlutterEngine属于静态缓存的,则不用销毁,这里应该返回false。
    boolean shouldDestroyEngineWithHost();
    //8、当FlutterEngine已经attach到另一个Activity时这个Activity就需要与FlutterEngine断开。
    void detachFromFlutterEngine();
    //9、获取dart主入口,默认时main。
    //可以在AndroidManifest.xml中给Activity设置io.flutter.Entrypoint的meta自定义。
    @NonNull
    String getDartEntrypointFunctionName();
    //10、返回app bundle dart代码存在的路径。
    @NonNull
    String getAppBundlePath();
    //11、获取初始路由地址。
    //默认先从intent中解析route的值,没有就去meta-data解析io.flutter.InitialRoute的值,没有就返回null。
    @Nullable
    String getInitialRoute();
    //12、获取渲染模式,用在FlutterView呈现FlutterEngine引擎渲染效果。
    @NonNull
    RenderMode getRenderMode();
    //13、获取Transparency模式,用在FlutterView呈现FlutterEngine引擎渲染效果。
    @NonNull
    TransparencyMode getTransparencyMode();
	//14、提供一个Flutter开屏图片,默认有配置。
	//通过meta-data配置io.flutter.embedding.android.SplashScreenDrawable可生效。
    @Nullable
    SplashScreen provideSplashScreen();
    //15、返回一个用来渲染FlutterView的FlutterEngine引擎。
    //如果返回null则框架会自动新建一个FlutterEngine引擎实例,默认就是自动新建,我们可以重写复用等。
    @Nullable
    FlutterEngine provideFlutterEngine(@NonNull Context context);
    //16、创建和配置platform plugin。
    @Nullable
    PlatformPlugin providePlatformPlugin(
        @Nullable Activity activity, @NonNull FlutterEngine flutterEngine);
    void configureFlutterEngine(@NonNull FlutterEngine flutterEngine);
    void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine);
    boolean shouldAttachEngineToActivity();
    void onFlutterSurfaceViewCreated(@NonNull FlutterSurfaceView flutterSurfaceView);
    void onFlutterTextureViewCreated(@NonNull FlutterTextureView flutterTextureView);
    void onFlutterUiDisplayed();
    void onFlutterUiNoLongerDisplayed();
    boolean shouldRestoreAndSaveState();
  }
}

可以看到FlutterActivityAndFragmentDelegate.Host是 Flutter Android 平台层实现与标准 Activity/Fragment 之间的一个接口约定层,FlutterActivity 实现了这个接口的一系列方法,这些接口的含义上面也列举了,所以我们下面重心回到标准 Android Activity 生命周期线,如下:

public class FlutterActivity extends Activity
    implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner {
  ......
  //步骤1、重点!关联Activity、Fragment与Flutter的接口桥梁委托实现
  protected FlutterActivityAndFragmentDelegate delegate;
  ......
  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
  	//步骤2、将清单文件中标准配置的主题切换回普通主题。很巧妙的让launch app和initialized后activity主题发生变化。
  	//普通主题通过io.flutter.embedding.android.NormalTheme的meta-data配置。
  	//清单标准配置的是一个图标、启动后执行到这里被换成标准纯背景色,两个主题不要对窗体size进行差异配置,不然会抖动。
    switchLaunchThemeForNormalTheme();

    super.onCreate(savedInstanceState);
	//步骤3、创建一个委托代理类实例,然后调用他的一系列方法。
    delegate = new FlutterActivityAndFragmentDelegate(this);
    delegate.onAttach(this);
    delegate.onRestoreInstanceState(savedInstanceState);
	//步骤4、标准AAC操作,不解释。
    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
	//步骤5、从Activity的Intent中解析background_mode字段看是transparent还是opaque。
	//透明则通过getWindow().setBackgroundDrawable设置为透明,否则保持NormalTheme的暗黑适配纯色背景。
    configureWindowForTransparency();
    //步骤6、创建一个View让Activity显示,这就是Flutter的View容器。
    setContentView(createFlutterView());
    //步骤7、官方对全屏状态栏的兼容配置。。。
    configureStatusBarForFullscreenFlutterExperience();
  }
  ......

  //步骤8、创建并返回一个View用来给Activity显示。
  @NonNull
  private View createFlutterView() {
    return delegate.onCreateView(
        null /* inflater */, null /* container */, null /* savedInstanceState */);
  }

  //步骤9、官方对全屏状态栏的兼容配置。
  //这些flag不用解释了吧,标准安卓操作。
  //记住这个坑即可,我们如果想修改FlutterActivity的这玩意就在他之后覆盖即可。
  private void configureStatusBarForFullscreenFlutterExperience() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      Window window = getWindow();
      window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
      window.setStatusBarColor(0x40000000);
      window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI);
    }
  }
  
  //步骤10、生命周期回调处理,AAC调用、delegate对应方法触发等
  @Override
  protected void onStart() {
    super.onStart();
    lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
    //判断delegate是否不为null
    if (stillAttachedForEvent("onStart")) {
      delegate.onStart();
    }
  }
	
  //步骤11、同步骤10的一堆回调类似触发,省略实现。。。
  @Override
  protected void onResume() {......}
  @Override
  public void onPostResume() {......}
  @Override
  protected void onPause() {......}
  @Override
  protected void onStop() {......}
  @Override
  protected void onSaveInstanceState(Bundle outState) {......}
  @Override
  protected void onDestroy() {......}
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {......}
  @Override
  protected void onNewIntent(@NonNull Intent intent) {......}
  @Override
  public void onBackPressed() {......}
  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @

以上是关于Flutter Android 端 Activity/Fragment 流程源码分析的主要内容,如果未能解决你的问题,请参考以下文章

FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 BasicMessageChannel 通信 )

Flutter Android 端 Activity/Fragment 流程源码分析

Flutter如何与Native(Android)进行交互

Flutter Android 端 FlutterView 相关流程源码分析

Flutter Android 端 FlutterView 相关流程源码分析

Flutter Android 端 FlutterView 相关流程源码分析