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 端 FlutterInjector 及依赖流程源码分析》
- 《Flutter Android 端 FlutterEngine Java 相关流程源码分析》
- 《Flutter Android 端 FlutterView 相关流程源码分析》
- 《Flutter 绘制动机 VSYNC 流程源码全方位分析》
- 《Flutter 安卓 Platform 与 Dart 端消息通信方式 Channel 源码解析》
背景
前面文章我们分析了 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以上是关于Flutter Android 端 Activity/Fragment 流程源码分析的主要内容,如果未能解决你的问题,请参考以下文章
FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 BasicMessageChannel 通信 )
Flutter Android 端 Activity/Fragment 流程源码分析
Flutter Android 端 FlutterView 相关流程源码分析