Flutter Android启动源码分析(二)
前言
上篇文章Flutter Android启动源码分析(一)中主要对FlutterApplicaiton和FlutterActivity进行了分析,在FlutterActivity源码部分中FlutterActivityAndFragmentDelegate这个类一直被提到,这篇文章我们就主要分析一下它做了哪些事情
FlutterActivityAndFragmentDelegate
- 作用
- FlutterActivity和FlutterFragment之间相同的Flutter逻辑的委托
- 为什么要用这个类
- 假设可以在Activity中放置一个 Fragment,那么在FlutterActivity中使用一个FlutterFragment更有意义。Fragment支持库为应用程序增加了100k二进制大小,而全Flutter应用程序不需要二进制命中。因此,得出的结论是,Flutter必须基于AOSP(Android Open Source Project: Android 开源项目)Activity 提供FlutterActivity,并为应用程序添加开发人员提供独立的 FlutterFragment
- 大概意思就是FlutterActivity和FlutterFragment是相互独立的,所以需要一个代理委托类去处理它们之间相同的逻辑
成员变量
// Host实现类对象即FlutterActivity
@NonNull private Host host;
// Flutter执行环境
@Nullable private FlutterEngine flutterEngine;
// 闪屏View,直到FlutterView显示第一帧
@Nullable private FlutterSplashView flutterSplashView;
// Flutter UI
@Nullable private FlutterView flutterView;
// 安卓平台的插件实现
@Nullable private PlatformPlugin platformPlugin;
// 是否是Host实现类提供FlutterEngine
private boolean isFlutterEngineFromHost;
构造函数
FlutterActivityAndFragmentDelegate(@NonNull Host host) {
this.host = host;
}
在FlutterActivity的onCreate方法里里实例化FlutterActivityAndFragmentDelegate并传递当前FA上下文对象,
然后调用onAttach、onActivityCreated、onCreateView,下面我们对这三个方法进行逐一分析
// FlutterActivity 删除部分源码
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
delegate = new FlutterActivityAndFragmentDelegate(this);
delegate.onAttach(this);
delegate.onActivityCreated(savedInstanceState);
setContentView(createFlutterView());
}
@NonNull
private View createFlutterView() {
return delegate.onCreateView(
null /* inflater */, null /* container */, null /* savedInstanceState */);
}
onAttach
void onAttach(@NonNull Context context) {
ensureAlive();
if (flutterEngine == null) {
// 1
setupFlutterEngine();
}
// 2
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);
// 3
if (host.shouldAttachEngineToActivity()) {
flutterEngine
.getActivityControlSurface()
.attachToActivity(host.getActivity(), host.getLifecycle());
}
// 4
host.configureFlutterEngine(flutterEngine);
}
-
实例化FlutterEngine
void setupFlutterEngine() { String cachedEngineId = host.getCachedEngineId(); if (cachedEngineId != null) { flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId); isFlutterEngineFromHost = true; if (flutterEngine == null) { throw new IllegalStateException( "The requested cached FlutterEngine did not exist in the FlutterEngineCache: '" + cachedEngineId + "'"); } return; } flutterEngine = host.provideFlutterEngine(host.getContext()); if (flutterEngine != null) { isFlutterEngineFromHost = true; return; } flutterEngine = new FlutterEngine( host.getContext(), host.getFlutterShellArgs().toArray(), /*automaticallyRegisterPlugins=*/ false, /*willProvideRestorationData=*/ host.shouldRestoreAndSaveState()); isFlutterEngineFromHost = false; }
首先会判断是否有缓存的EngineId,如果有,去FlutterEngineCache缓存区去取到并实例化,
如果没有,会去判断Host实现类(FlutterActivity是否有提供Engine),这个的话目前版本是返回null,
// FlutterActivity @Nullable @Override public FlutterEngine provideFlutterEngine(@NonNull Context context) { // No-op. Hook for subclasses. return null; }
最后就会直接去实例化一个新的Engine,然后设置isFlutterEngineFromHost 为false,说明此Engine非Host实现类提供
我们大概看下FlutterEngine的构造函数
public FlutterEngine( @NonNull Context context, @NonNull FlutterLoader flutterLoader, @NonNull FlutterJNI flutterJNI, @NonNull PlatformViewsController platformViewsController, @Nullable String[] dartVmArgs, boolean automaticallyRegisterPlugins, boolean waitForRestorationData) { this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets()); this.dartExecutor.onAttachedToJNI(); accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI); keyEventChannel = new KeyEventChannel(dartExecutor); lifecycleChannel = new LifecycleChannel(dartExecutor); localizationChannel = new LocalizationChannel(dartExecutor); mouseCursorChannel = new MouseCursorChannel(dartExecutor); navigationChannel = new NavigationChannel(dartExecutor); platformChannel = new PlatformChannel(dartExecutor); restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData); settingsChannel = new SettingsChannel(dartExecutor); systemChannel = new SystemChannel(dartExecutor); textInputChannel = new TextInputChannel(dartExecutor); this.localizationPlugin = new LocalizationPlugin(context, localizationChannel); this.flutterJNI = flutterJNI; flutterLoader.startInitialization(context.getApplicationContext()); flutterLoader.ensureInitializationComplete(context, dartVmArgs); flutterJNI.addEngineLifecycleListener(engineLifecycleListener); flutterJNI.setPlatformViewsController(platformViewsController); flutterJNI.setLocalizationPlugin(localizationPlugin); attachToJni(); // TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if // possible. this.renderer = new FlutterRenderer(flutterJNI); this.platformViewsController = platformViewsController; this.platformViewsController.onAttachedToJNI(); this.pluginRegistry = new FlutterEnginePluginRegistry(context.getApplicationContext(), this, flutterLoader); if (automaticallyRegisterPlugins) { registerPlugins(); } }
- dartExecutor实例化
- 一些系统channel初始化
- FlutterJNI、PlatformViewsController、FlutterRender、FlutterLoader初始化
- 实例化FlutterEnginePluginRegistry插件注册表
FlutterRender 就是与提供的RenderSurface协同工作,将Flutter 像素绘制到Android View层次结构中。FlutterRender管理渲染纹理,并通过JNI将一些Java调用转发到本地 Flutter代码
FlutterLoader就是在应用程序APK中查找Flutter资源,并加载Flutter的本机库
这两个大家可以自己去看一下,就不多提及了
-
实例化PlatformPlugin
// FlutterActivity @Nullable @Override public PlatformPlugin providePlatformPlugin( @Nullable Activity activity, @NonNull FlutterEngine flutterEngine) { if (activity != null) { return new PlatformPlugin(getActivity(), flutterEngine.getPlatformChannel()); } else { return null; } }
可以看到FlutterActivity重写这个方法并实例化一个新的PlatformPlugin
这里有一个注意点:如果FlutterFragment 连接到一个新的Activity上的时候,都要重新去创建一个PlatformPlugin
PlatformPlugin的话大家可以自己去看,就是平台提供的原生插件,如:状态栏操作、剪贴板等Plugin
-
attachToActivity
// FlutterActivity @Override public boolean shouldAttachEngineToActivity() { return true; }
这里话默认是返回true,建立Activity和Engine的关联关系
attachToActivity方法的作用就是通知当前连接到FlutterEngine的所有插件,将它们附加到Activity
// FlutterEnginePluginRegistry 插件注册表 @Override public void attachToActivity(@NonNull Activity activity, @NonNull Lifecycle lifecycle) { detachFromAndroidComponent(); this.activity = activity; this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity, lifecycle); flutterEngine .getPlatformViewsController() .attach(activity, flutterEngine.getRenderer(), flutterEngine.getDartExecutor()); for (ActivityAware activityAware : activityAwarePlugins.values()) { if (isWaitingForActivityReattachment) { activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding); } else { activityAware.onAttachedToActivity(activityPluginBinding); } } isWaitingForActivityReattachment = false; }
FlutterEnginePluginRegistry这个类大家有兴趣可以看下,其实就是一个Engine插件注册表,这里不做过多分析
它是在FlutterEngine的构造函数里进行实例化的
-
configureFlutterEngine
// FlutterActivity @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { registerPlugins(flutterEngine); }
注册pubspec.yaml里的原生插件,所以像上篇文章所说,新版本帮我们进行了自动注册。
onActivityCreated
void onActivityCreated(@Nullable Bundle bundle) {
Bundle pluginState = null;
byte[] frameworkState = null;
if (bundle != null) {
pluginState = bundle.getBundle(PLUGINS_RESTORATION_BUNDLE_KEY);
frameworkState = bundle.getByteArray(FRAMEWORK_RESTORATION_BUNDLE_KEY);
}
if (host.shouldRestoreAndSaveState()) {
flutterEngine.getRestorationChannel().setRestorationData(frameworkState);
}
if (host.shouldAttachEngineToActivity()) {
flutterEngine.getActivityControlSurface().onRestoreInstanceState(pluginState);
}
}
这个我们不做过多分析,就是为插件和Activity提供恢复数据
onCreateView
View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ensureAlive();
if (host.getRenderMode() == RenderMode.surface) {
FlutterSurfaceView flutterSurfaceView =
new FlutterSurfaceView(
host.getActivity(), host.getTransparencyMode() == TransparencyMode.transparent);
host.onFlutterSurfaceViewCreated(flutterSurfaceView);
flutterView = new FlutterView(host.getActivity(), flutterSurfaceView);
} else {
FlutterTextureView flutterTextureView = new FlutterTextureView(host.getActivity());
host.onFlutterTextureViewCreated(flutterTextureView);
flutterView = new FlutterView(host.getActivity(), flutterTextureView);
}
flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);
flutterSplashView = new FlutterSplashView(host.getContext());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
flutterSplashView.setId(View.generateViewId());
} else {
flutterSplashView.setId(486947586);
}
flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen());
flutterView.attachToFlutterEngine(flutterEngine);
return flutterSplashView;
}
-
首先会判断渲染模式
// FlutterActivity @NonNull @Override public RenderMode getRenderMode() { return getBackgroundMode() == BackgroundMode.opaque ? RenderMode.surface : RenderMode.texture; } @NonNull protected BackgroundMode getBackgroundMode() { if (getIntent().hasExtra(EXTRA_BACKGROUND_MODE)) { return BackgroundMode.valueOf(getIntent().getStringExtra(EXTRA_BACKGROUND_MODE)); } else { return BackgroundMode.opaque; } }
框架提供了两种渲染模式: RenderMode.surface , RenderMode.texture,Flutter框架默认使用Surface进行渲染
-
然后会实例化一个非透明的FlutterSurfaceView,并设置onFlutterSurfaceViewCreated回调
public enum BackgroundMode { /** Indicates a FlutterActivity with an opaque background. This is the default. */ opaque, /** Indicates a FlutterActivity with a transparent background. */ transparent }
-
然后接着创建拥有FlutterSurfaceView的FlutterView,上面有提到这个FlutterView就是用来在安卓设备上显示Flutter UI
flutterView = new FlutterView(host.getActivity(), flutterSurfaceView);
TextureView也是一样,不去分析
-
然后会添加一个绘制第一帧的监听器
flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);
-
接着会创建一个FlutterSplashView,然后调用displayFlutterViewWithSplash 方法在FlutterView上显示闪屏界面,直到绘制了第一帧
flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen()); //FlutterActivity @Nullable @Override public SplashScreen provideSplashScreen() { Drawable manifestSplashDrawable = getSplashScreenFromManifest(); if (manifestSplashDrawable != null) { return new DrawableSplashScreen(manifestSplashDrawable); } else { return null; } } @Nullable @SuppressWarnings("deprecation") private Drawable getSplashScreenFromManifest() { try { ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); Bundle metadata = activityInfo.metaData; int splashScreenId = metadata != null ? metadata.getInt(SPLASH_SCREEN_META_DATA_KEY) : 0; return splashScreenId != 0 ? Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP ? getResources().getDrawable(splashScreenId, getTheme()) : getResources().getDrawable(splashScreenId) : null; } catch (PackageManager.NameNotFoundException e) { // This is never expected to happen. return null; } } // FlutterActivityLaunchConfigs static final String SPLASH_SCREEN_META_DATA_KEY ="io.flutter.embedding.android.SplashScreenDrawable"; // AndroidManifest.xml <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" />
可以看到FlutterActivity重写provideSplashScreen,返回我们在AndroidManifest.xml设置的闪屏drawable
-
flutterView.attachToFlutterEngine(flutterEngine);
然后将此FlutterView连接到给定的 FlutterEngine。此FlutterView将开始呈现给定FlutterEngine绘制的UI。并且这个FlutterView还将开始将交互事件从此FlutterView转发到给定的FlutterEngine例如,用户触摸事件,可访问性事件,键盘事件等
-
返回flutterSplashView到FlutterActivity。到此刻为止,FlutterActivityAndFragmentDelegate 的onAttach方法已全部分析完毕
-
同时在添加SplashScreenDrawable之后,也能解决安卓启动黑屏的问题—>从MainActivity的setContentView直到收到Flutter绘制第一帧的回调时,才会关闭这个splashView
接下来我们分析onStart方法
onStart
// FlutterActivity
@Override
protected void onStart() {
super.onStart();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
delegate.onStart();
}
// FlutterActivityAndFragmentDelegate
void onStart() {
Log.v(TAG, "onStart()");
ensureAlive();
doInitialFlutterViewRun();
}
可以看到FlutterActivity.onStart调用了FlutterActivityAndFragmentDelegate.onStart方法,然后其调用了doInitialFlutterViewRun方法
这个方法的话就是首次开始在FlutterView中运行Dart
private void doInitialFlutterViewRun() {
// 1
if (host.getCachedEngineId() != null) {
return;
}
if (flutterEngine.getDartExecutor().isExecutingDart()) {
return;
}
// 2
if (host.getInitialRoute() != null) {
flutterEngine.getNavigationChannel().setInitialRoute(host.getInitialRoute());
}
// 3
DartExecutor.DartEntrypoint entrypoint =
new DartExecutor.DartEntrypoint(
host.getAppBundlePath(), host.getDartEntrypointFunctionName());
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
}
-
首先判断engine缓存id是否为空,具体实现在FlutterActivity
// FlutterActivity @Override @Nullable public String getCachedEngineId() { return getIntent().getStringExtra(EXTRA_CACHED_ENGINE_ID); }
这里说明一下,Flutter框架是每次都去实例化一个新的FlutterEngine,上面有提到,所以这里恒为null。具体使用场景以后再说
然后会判断Dart是否执行
-
这里会设置执行 Dart代码之前接收Flutter应用程序的初始路径,以确保初始路径能够及时应用。
//FlutterActivity @NonNull public String getInitialRoute() { if (getIntent().hasExtra(EXTRA_INITIAL_ROUTE)) { return getIntent().getStringExtra(EXTRA_INITIAL_ROUTE); } try { ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); Bundle metadata = activityInfo.metaData; String desiredInitialRoute = metadata != null ? metadata.getString(INITIAL_ROUTE_META_DATA_KEY) : null; return desiredInitialRoute != null ? desiredInitialRoute : DEFAULT_INITIAL_ROUTE; } catch (PackageManager.NameNotFoundException e) { return DEFAULT_INITIAL_ROUTE; } }
设置初始化路径可以通过Intent,还可以在Android manifest.定义指定INITIAL_ROUTE_META_DATA_KEY
这里我们不多聊,这个最后返回的是DEFAULT_INITIAL_ROUTE,默认路径
//FlutterActivityLaunchConfigs static final String DEFAULT_INITIAL_ROUTE = "/";
-
然后配置Dart代码执行入口点并且去执行它
host.getAppBundlePath返回的是默认路径
private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets";
host.getDartEntrypointFunctionName()返回的是也是默认启动方法名,
static final String DEFAULT_DART_ENTRYPOINT = "main";
就是我们main.dart里的这个main方法
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); }
//DartExecutor 配置,引导并开始执行Dart代码。 public void executeDartEntrypoint(@NonNull DartEntrypoint dartEntrypoint) { if (isApplicationRunning) { Log.w(TAG, "Attempted to run a DartExecutor that is already running."); return; } Log.v(TAG, "Executing Dart entrypoint: " + dartEntrypoint); flutterJNI.runBundleAndSnapshotFromLibrary( dartEntrypoint.pathToBundle, dartEntrypoint.dartEntrypointFunctionName, null, assetManager); isApplicationRunning = true; }
可以看到这里设置 isApplicationRunning = true,代表程序正在运行,
//DartExecutor public boolean isExecutingDart() { return isApplicationRunning; }
判断是否正在执行dart代码也是通过此变量
-
FlutterJNI类是Flutter嵌入的Java代码和Flutter引擎的C / C ++代码之间的接口。这块大家自己去看吧
-
到此刻,一个flutter程序就正常运行起来了,接着就是执行dart代码和我们自己的业务逻辑
接下来,我们看下生命周期Channel LifecycleChannel
void onResume() {
Log.v(TAG, "onResume()");
ensureAlive();
flutterEngine.getLifecycleChannel().appIsResumed();
}
它主要是将Android生命周期事件发送到Flutter,onPause、onStop、onDetach也做了同样处理
FlutterActivity onDestroy
@Override
protected void onDestroy() {
super.onDestroy();
delegate.onDestroyView();
delegate.onDetach();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
这里主要是做一些清除引用,销毁资源的一些操作。大家可以自行阅读源码
总结
通过这篇文章我们可以大概的看到
- FlutterActivityAndFragmentDelegate是如何去代理FlutterActivity的工作
- FlutterActivityAndFragmentDelegate是如何将FlutterEngine和FlutterActivity连接在一起,并执行dart代码,启动应用程序
- FlutterRender、FlutterJNI、FlutterLoader大家可以自己去结合源码看一下,基本的启动流程就是这样
下篇文章我会通过一个Android 项目嵌入Flutter Module的混合工程来让大家更直观的看到Flutter在Android上到底是如何去展示的
前言
上篇文章Flutter Android启动源码分析(一)中主要对FlutterApplicaiton和FlutterActivity进行了分析,在FlutterActivity源码部分中FlutterActivityAndFragmentDelegate这个类一直被提到,这篇文章我们就主要分析一下它做了哪些事情
FlutterActivityAndFragmentDelegate
- 作用
- FlutterActivity和FlutterFragment之间相同的Flutter逻辑的委托
- 为什么要用这个类
- 假设可以在Activity中放置一个 Fragment,那么在FlutterActivity中使用一个FlutterFragment更有意义。Fragment支持库为应用程序增加了100k二进制大小,而全Flutter应用程序不需要二进制命中。因此,得出的结论是,Flutter必须基于AOSP(Android Open Source Project: Android 开源项目)Activity 提供FlutterActivity,并为应用程序添加开发人员提供独立的 FlutterFragment
- 大概意思就是FlutterActivity和FlutterFragment是相互独立的,所以需要一个代理委托类去处理它们之间相同的逻辑
成员变量
// Host实现类对象即FlutterActivity
@NonNull private Host host;
// Flutter执行环境
@Nullable private FlutterEngine flutterEngine;
// 闪屏View,直到FlutterView显示第一帧
@Nullable private FlutterSplashView flutterSplashView;
// Flutter UI
@Nullable private FlutterView flutterView;
// 安卓平台的插件实现
@Nullable private PlatformPlugin platformPlugin;
// 是否是Host实现类提供FlutterEngine
private boolean isFlutterEngineFromHost;
构造函数
FlutterActivityAndFragmentDelegate(@NonNull Host host) {
this.host = host;
}
在FlutterActivity的onCreate方法里里实例化FlutterActivityAndFragmentDelegate并传递当前FA上下文对象,
然后调用onAttach、onActivityCreated、onCreateView,下面我们对这三个方法进行逐一分析
// FlutterActivity 删除部分源码
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
delegate = new FlutterActivityAndFragmentDelegate(this);
delegate.onAttach(this);
delegate.onActivityCreated(savedInstanceState);
setContentView(createFlutterView());
}
@NonNull
private View createFlutterView() {
return delegate.onCreateView(
null /* inflater */, null /* container */, null /* savedInstanceState */);
}
onAttach
void onAttach(@NonNull Context context) {
ensureAlive();
if (flutterEngine == null) {
// 1
setupFlutterEngine();
}
// 2
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);
// 3
if (host.shouldAttachEngineToActivity()) {
flutterEngine
.getActivityControlSurface()
.attachToActivity(host.getActivity(), host.getLifecycle());
}
// 4
host.configureFlutterEngine(flutterEngine);
}
-
实例化FlutterEngine
void setupFlutterEngine() { String cachedEngineId = host.getCachedEngineId(); if (cachedEngineId != null) { flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId); isFlutterEngineFromHost = true; if (flutterEngine == null) { throw new IllegalStateException( "The requested cached FlutterEngine did not exist in the FlutterEngineCache: '" + cachedEngineId + "'"); } return; } flutterEngine = host.provideFlutterEngine(host.getContext()); if (flutterEngine != null) { isFlutterEngineFromHost = true; return; } flutterEngine = new FlutterEngine( host.getContext(), host.getFlutterShellArgs().toArray(), /*automaticallyRegisterPlugins=*/ false, /*willProvideRestorationData=*/ host.shouldRestoreAndSaveState()); isFlutterEngineFromHost = false; }
首先会判断是否有缓存的EngineId,如果有,去FlutterEngineCache缓存区去取到并实例化,
如果没有,会去判断Host实现类(FlutterActivity是否有提供Engine),这个的话目前版本是返回null,
// FlutterActivity @Nullable @Override public FlutterEngine provideFlutterEngine(@NonNull Context context) { // No-op. Hook for subclasses. return null; }
最后就会直接去实例化一个新的Engine,然后设置isFlutterEngineFromHost 为false,说明此Engine非Host实现类提供
我们大概看下FlutterEngine的构造函数
public FlutterEngine( @NonNull Context context, @NonNull FlutterLoader flutterLoader, @NonNull FlutterJNI flutterJNI, @NonNull PlatformViewsController platformViewsController, @Nullable String[] dartVmArgs, boolean automaticallyRegisterPlugins, boolean waitForRestorationData) { this.dartExecutor = new DartExecutor(flutterJNI, context.getAssets()); this.dartExecutor.onAttachedToJNI(); accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI); keyEventChannel = new KeyEventChannel(dartExecutor); lifecycleChannel = new LifecycleChannel(dartExecutor); localizationChannel = new LocalizationChannel(dartExecutor); mouseCursorChannel = new MouseCursorChannel(dartExecutor); navigationChannel = new NavigationChannel(dartExecutor); platformChannel = new PlatformChannel(dartExecutor); restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData); settingsChannel = new SettingsChannel(dartExecutor); systemChannel = new SystemChannel(dartExecutor); textInputChannel = new TextInputChannel(dartExecutor); this.localizationPlugin = new LocalizationPlugin(context, localizationChannel); this.flutterJNI = flutterJNI; flutterLoader.startInitialization(context.getApplicationContext()); flutterLoader.ensureInitializationComplete(context, dartVmArgs); flutterJNI.addEngineLifecycleListener(engineLifecycleListener); flutterJNI.setPlatformViewsController(platformViewsController); flutterJNI.setLocalizationPlugin(localizationPlugin); attachToJni(); // TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if // possible. this.renderer = new FlutterRenderer(flutterJNI); this.platformViewsController = platformViewsController; this.platformViewsController.onAttachedToJNI(); this.pluginRegistry = new FlutterEnginePluginRegistry(context.getApplicationContext(), this, flutterLoader); if (automaticallyRegisterPlugins) { registerPlugins(); } }
- dartExecutor实例化
- 一些系统channel初始化
- FlutterJNI、PlatformViewsController、FlutterRender、FlutterLoader初始化
- 实例化FlutterEnginePluginRegistry插件注册表
FlutterRender 就是与提供的RenderSurface协同工作,将Flutter 像素绘制到Android View层次结构中。FlutterRender管理渲染纹理,并通过JNI将一些Java调用转发到本地 Flutter代码
FlutterLoader就是在应用程序APK中查找Flutter资源,并加载Flutter的本机库
这两个大家可以自己去看一下,就不多提及了
-
实例化PlatformPlugin
// FlutterActivity @Nullable @Override public PlatformPlugin providePlatformPlugin( @Nullable Activity activity, @NonNull FlutterEngine flutterEngine) { if (activity != null) { return new PlatformPlugin(getActivity(), flutterEngine.getPlatformChannel()); } else { return null; } }
可以看到FlutterActivity重写这个方法并实例化一个新的PlatformPlugin
这里有一个注意点:如果FlutterFragment 连接到一个新的Activity上的时候,都要重新去创建一个PlatformPlugin
PlatformPlugin的话大家可以自己去看,就是平台提供的原生插件,如:状态栏操作、剪贴板等Plugin
-
attachToActivity
// FlutterActivity @Override public boolean shouldAttachEngineToActivity() { return true; }
这里话默认是返回true,建立Activity和Engine的关联关系
attachToActivity方法的作用就是通知当前连接到FlutterEngine的所有插件,将它们附加到Activity
// FlutterEnginePluginRegistry 插件注册表 @Override public void attachToActivity(@NonNull Activity activity, @NonNull Lifecycle lifecycle) { detachFromAndroidComponent(); this.activity = activity; this.activityPluginBinding = new FlutterEngineActivityPluginBinding(activity, lifecycle); flutterEngine .getPlatformViewsController() .attach(activity, flutterEngine.getRenderer(), flutterEngine.getDartExecutor()); for (ActivityAware activityAware : activityAwarePlugins.values()) { if (isWaitingForActivityReattachment) { activityAware.onReattachedToActivityForConfigChanges(activityPluginBinding); } else { activityAware.onAttachedToActivity(activityPluginBinding); } } isWaitingForActivityReattachment = false; }
FlutterEnginePluginRegistry这个类大家有兴趣可以看下,其实就是一个Engine插件注册表,这里不做过多分析
它是在FlutterEngine的构造函数里进行实例化的
-
configureFlutterEngine
// FlutterActivity @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { registerPlugins(flutterEngine); }
注册pubspec.yaml里的原生插件,所以像上篇文章所说,新版本帮我们进行了自动注册。
onActivityCreated
void onActivityCreated(@Nullable Bundle bundle) {
Bundle pluginState = null;
byte[] frameworkState = null;
if (bundle != null) {
pluginState = bundle.getBundle(PLUGINS_RESTORATION_BUNDLE_KEY);
frameworkState = bundle.getByteArray(FRAMEWORK_RESTORATION_BUNDLE_KEY);
}
if (host.shouldRestoreAndSaveState()) {
flutterEngine.getRestorationChannel().setRestorationData(frameworkState);
}
if (host.shouldAttachEngineToActivity()) {
flutterEngine.getActivityControlSurface().onRestoreInstanceState(pluginState);
}
}
这个我们不做过多分析,就是为插件和Activity提供恢复数据
onCreateView
View onCreateView(
LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ensureAlive();
if (host.getRenderMode() == RenderMode.surface) {
FlutterSurfaceView flutterSurfaceView =
new FlutterSurfaceView(
host.getActivity(), host.getTransparencyMode() == TransparencyMode.transparent);
host.onFlutterSurfaceViewCreated(flutterSurfaceView);
flutterView = new FlutterView(host.getActivity(), flutterSurfaceView);
} else {
FlutterTextureView flutterTextureView = new FlutterTextureView(host.getActivity());
host.onFlutterTextureViewCreated(flutterTextureView);
flutterView = new FlutterView(host.getActivity(), flutterTextureView);
}
flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);
flutterSplashView = new FlutterSplashView(host.getContext());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
flutterSplashView.setId(View.generateViewId());
} else {
flutterSplashView.setId(486947586);
}
flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen());
flutterView.attachToFlutterEngine(flutterEngine);
return flutterSplashView;
}
-
首先会判断渲染模式
// FlutterActivity @NonNull @Override public RenderMode getRenderMode() { return getBackgroundMode() == BackgroundMode.opaque ? RenderMode.surface : RenderMode.texture; } @NonNull protected BackgroundMode getBackgroundMode() { if (getIntent().hasExtra(EXTRA_BACKGROUND_MODE)) { return BackgroundMode.valueOf(getIntent().getStringExtra(EXTRA_BACKGROUND_MODE)); } else { return BackgroundMode.opaque; } }
框架提供了两种渲染模式: RenderMode.surface , RenderMode.texture,Flutter框架默认使用Surface进行渲染
-
然后会实例化一个非透明的FlutterSurfaceView,并设置onFlutterSurfaceViewCreated回调
public enum BackgroundMode { /** Indicates a FlutterActivity with an opaque background. This is the default. */ opaque, /** Indicates a FlutterActivity with a transparent background. */ transparent }
-
然后接着创建拥有FlutterSurfaceView的FlutterView,上面有提到这个FlutterView就是用来在安卓设备上显示Flutter UI
flutterView = new FlutterView(host.getActivity(), flutterSurfaceView);
TextureView也是一样,不去分析
-
然后会添加一个绘制第一帧的监听器
flutterView.addOnFirstFrameRenderedListener(flutterUiDisplayListener);
-
接着会创建一个FlutterSplashView,然后调用displayFlutterViewWithSplash 方法在FlutterView上显示闪屏界面,直到绘制了第一帧
flutterSplashView.displayFlutterViewWithSplash(flutterView, host.provideSplashScreen()); //FlutterActivity @Nullable @Override public SplashScreen provideSplashScreen() { Drawable manifestSplashDrawable = getSplashScreenFromManifest(); if (manifestSplashDrawable != null) { return new DrawableSplashScreen(manifestSplashDrawable); } else { return null; } } @Nullable @SuppressWarnings("deprecation") private Drawable getSplashScreenFromManifest() { try { ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); Bundle metadata = activityInfo.metaData; int splashScreenId = metadata != null ? metadata.getInt(SPLASH_SCREEN_META_DATA_KEY) : 0; return splashScreenId != 0 ? Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP ? getResources().getDrawable(splashScreenId, getTheme()) : getResources().getDrawable(splashScreenId) : null; } catch (PackageManager.NameNotFoundException e) { // This is never expected to happen. return null; } } // FlutterActivityLaunchConfigs static final String SPLASH_SCREEN_META_DATA_KEY ="io.flutter.embedding.android.SplashScreenDrawable"; // AndroidManifest.xml <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" />
可以看到FlutterActivity重写provideSplashScreen,返回我们在AndroidManifest.xml设置的闪屏drawable
-
flutterView.attachToFlutterEngine(flutterEngine);
然后将此FlutterView连接到给定的 FlutterEngine。此FlutterView将开始呈现给定FlutterEngine绘制的UI。并且这个FlutterView还将开始将交互事件从此FlutterView转发到给定的FlutterEngine例如,用户触摸事件,可访问性事件,键盘事件等
-
返回flutterSplashView到FlutterActivity。到此刻为止,FlutterActivityAndFragmentDelegate 的onAttach方法已全部分析完毕
接下来我们分析onStart方法
onStart
// FlutterActivity
@Override
protected void onStart() {
super.onStart();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
delegate.onStart();
}
// FlutterActivityAndFragmentDelegate
void onStart() {
Log.v(TAG, "onStart()");
ensureAlive();
doInitialFlutterViewRun();
}
可以看到FlutterActivity.onStart调用了FlutterActivityAndFragmentDelegate.onStart方法,然后其调用了doInitialFlutterViewRun方法
这个方法的话就是首次开始在FlutterView中运行Dart
private void doInitialFlutterViewRun() {
// 1
if (host.getCachedEngineId() != null) {
return;
}
if (flutterEngine.getDartExecutor().isExecutingDart()) {
return;
}
// 2
if (host.getInitialRoute() != null) {
flutterEngine.getNavigationChannel().setInitialRoute(host.getInitialRoute());
}
// 3
DartExecutor.DartEntrypoint entrypoint =
new DartExecutor.DartEntrypoint(
host.getAppBundlePath(), host.getDartEntrypointFunctionName());
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
}
-
首先判断engine缓存id是否为空,具体实现在FlutterActivity
// FlutterActivity @Override @Nullable public String getCachedEngineId() { return getIntent().getStringExtra(EXTRA_CACHED_ENGINE_ID); }
这里说明一下,Flutter框架是每次都去实例化一个新的FlutterEngine,上面有提到,所以这里恒为null。具体使用场景以后再说
然后会判断Dart是否执行
-
这里会设置执行 Dart代码之前接收Flutter应用程序的初始路径,以确保初始路径能够及时应用。
//FlutterActivity @NonNull public String getInitialRoute() { if (getIntent().hasExtra(EXTRA_INITIAL_ROUTE)) { return getIntent().getStringExtra(EXTRA_INITIAL_ROUTE); } try { ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); Bundle metadata = activityInfo.metaData; String desiredInitialRoute = metadata != null ? metadata.getString(INITIAL_ROUTE_META_DATA_KEY) : null; return desiredInitialRoute != null ? desiredInitialRoute : DEFAULT_INITIAL_ROUTE; } catch (PackageManager.NameNotFoundException e) { return DEFAULT_INITIAL_ROUTE; } }
设置初始化路径可以通过Intent,还可以在Android manifest.定义指定INITIAL_ROUTE_META_DATA_KEY
这里我们不多聊,这个最后返回的是DEFAULT_INITIAL_ROUTE,默认路径
//FlutterActivityLaunchConfigs static final String DEFAULT_INITIAL_ROUTE = "/";
-
然后配置Dart代码执行入口点并且去执行它
host.getAppBundlePath返回的是默认路径
private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets";
host.getDartEntrypointFunctionName()返回的是也是默认启动方法名,
static final String DEFAULT_DART_ENTRYPOINT = "main";
就是我们main.dart里的这个main方法
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); }
//DartExecutor 配置,引导并开始执行Dart代码。 public void executeDartEntrypoint(@NonNull DartEntrypoint dartEntrypoint) { if (isApplicationRunning) { Log.w(TAG, "Attempted to run a DartExecutor that is already running."); return; } Log.v(TAG, "Executing Dart entrypoint: " + dartEntrypoint); flutterJNI.runBundleAndSnapshotFromLibrary( dartEntrypoint.pathToBundle, dartEntrypoint.dartEntrypointFunctionName, null, assetManager); isApplicationRunning = true; }
可以看到这里设置 isApplicationRunning = true,代表程序正在运行,
//DartExecutor public boolean isExecutingDart() { return isApplicationRunning; }
判断是否正在执行dart代码也是通过此变量
-
FlutterJNI类是Flutter嵌入的Java代码和Flutter引擎的C / C ++代码之间的接口。这块大家自己去看吧
-
到此刻,一个flutter程序就正常运行起来了,接着就是执行dart代码和我们自己的业务逻辑
接下来,我们看下生命周期Channel LifecycleChannel
void onResume() {
Log.v(TAG, "onResume()");
ensureAlive();
flutterEngine.getLifecycleChannel().appIsResumed();
}
它主要是将Android生命周期事件发送到Flutter,onPause、onStop、onDetach也做了同样处理
FlutterActivity onDestroy
@Override
protected void onDestroy() {
super.onDestroy();
delegate.onDestroyView();
delegate.onDetach();
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
这里主要是做一些清除引用,销毁资源的一些操作。大家可以自行阅读源码
总结
通过这篇文章我们可以大概的看到
- FlutterActivityAndFragmentDelegate是如何去代理FlutterActivity的工作
- FlutterActivityAndFragmentDelegate是如何将FlutterEngine和FlutterActivity连接在一起,并执行dart代码,启动应用程序
- FlutterRender、FlutterJNI、FlutterLoader大家可以自己去结合源码看一下,基本的启动流程就是这样
- 在Android上,Flutter默认是作为一个Activity加载到嵌入器中。视图由FlutterView控制,它根据Flutter内容的构成和z-排序要求,将Flutter内容渲染为视图或纹理。
- Flutter架构综述
下篇文章我会通过一个Android 项目嵌入Flutter Module的混合工程来让大家更直观的看到Flutter在Android上到底是如何去展示的
本人技术水平有限,太深入的分析就不去涉及了。如有错误,请及时指正。当然也欢迎大家能给我一些指导性意见,我们一起进步
本人技术水平有限,太深入的分析就不去涉及了。如有错误,请及时指正。当然也欢迎大家能给我一些指导性意见,我们一起进步
本文地址:https://blog.csdn.net/fighting_android/article/details/108723708
上一篇: windows phone开发之图片上传
下一篇: 网易云音乐下载的歌曲怎么设置命名格式?
推荐阅读
-
android开机自启动原理与实现案例(附源码)
-
Netty源码分析之ChannelPipeline(二)—ChannelHandler的添加与删除
-
Mybaits 源码解析 (九)----- 全网最详细,没有之一:一级缓存和二级缓存源码分析
-
Android 8.1 源码_启动篇(二) -- 深入研究 zygote
-
Android启动页广告(腾讯广告联盟)解决方法及源码下载
-
Tomcat源码分析 (二)----- Tomcat整体架构及组件
-
Android开发关于Toast的源码分析
-
Android Service的启动过程分析
-
Android8.1 SystemUI源码分析之 电池时钟刷新
-
Tomcat源码分析 (六)----- Tomcat 启动过程(一)