赞
踩
相信大家在学习Flutter的开始阶段都看过Flutter的架构图,如下
我们知道Flutter的应用层代码由Dart编写,Framework层提供了一系列Widget和其它API,那么这些Dart编写的代码是如何在特定平台上执行的呢,这就要从Flutter的启动过程说起了,了解了Flutter的启动过程,这个问题便迎刃而解。
我们通过架构图可以看出Embedder是由特定的平台实现,它其实就是将Flutter移植到各平台的中间层代码。Embedder层是Flutter启动的关键,其在应用启动后,由平台原生模块通过调用该层的API执行一系列操作,比如渲染层体系的设置、相关线程的创建等,最主要的是通过Embedder层初始化Flutter Engine,Engine中会创建DartVM、各种服务协议的初始化、Platform Channels的初始化等等,而后就会在DartVM中执行dart编写的入口方法main方法。至此,Flutter模块就启动成功了。
安卓平台对应的Embedder层代码在engine源码的 /flutter/shell/platform/android/ 目录下。
我们来根据flutter create my_app
命令创建的Flutter项目demo来分析。
首先,my_app应用启动会先执行FlutterApplication
,我们来看下该类中的生命周期方法onCreate方法的实现
@Override
@CallSuper
public void onCreate() {
super.onCreate();
FlutterMain.startInitialization(this);
}
FlutterMain类即是Embedder层的代码,该类的startInitialization方法实现如下
public static void startInitialization(Context applicationContext) { startInitialization(applicationContext, new Settings()); } public static void startInitialization(Context applicationContext, Settings settings) { if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException("startInitialization must be called on the main thread"); } // Do not run startInitialization more than once. if (sSettings != null) { return; } sSettings = settings; long initStartTimestampMillis = SystemClock.uptimeMillis(); initConfig(applicationContext); initAot(applicationContext); initResources(applicationContext); System.loadLibrary("flutter"); long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis; nativeRecordStartTimestamp(initTimeMillis); }
由以上源码可知startInitialization方法需要在主线程中执行,该方法主要是初始化配置信息、初始化AOT模式下的变量(Debug下是JIT模式)、资源文件的初始化(主要是将asset目录下的flutter相关资源文件copy到私有目录下)等,最后会将以上初始化所用时间通过JNI方法传递到c++层做记录。
static void RecordStartTimestamp(JNIEnv* env,
jclass jcaller,
jlong initTimeMillis) {
int64_t initTimeMicros =
static_cast<int64_t>(initTimeMillis) * static_cast<int64_t>(1000);
blink::engine_main_enter_ts = Dart_TimelineGetMicros() - initTimeMicros;
}
关键java类的UML类图
FlutterApplication执行完onCreate方法后会执行启动页面MainActivity的生命周期方法。我们发现MainActivity的onCreate方法中并没有通过setContentView来设置显示的视图,由于MainActivity继承了FlutterActivity并重载了父类的onCreate方法,所以我们看下FlutterActivity的onCreate方法
private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
private final FlutterActivityEvents eventDelegate = delegate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
eventDelegate.onCreate(savedInstanceState);
}
FlutterActivity继承自Activity,那么视图的设置我们推测应该是在FlutterActivityDelegate的onCreate方法中,我们看下它的实现
@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 = viewFactory.createFlutterView(activity); if (flutterView == null) { FlutterNativeView nativeView = viewFactory.createFlutterNativeView(); flutterView = new FlutterView(activity, null, nativeView); flutterView.setLayoutParams(matchParent); activity.setContentView(flutterView); launchView = createLaunchView(); if (launchView != null) { addLaunchView(); } } if (loadIntent(activity.getIntent())) { return; } String appBundlePath = FlutterMain.findAppBundlePath(activity.getApplicationContext()); if (appBundlePath != null) { runBundle(appBundlePath); } }
我们发现代码中有一句activity.setContentView(flutterView);
即为当前MainActivity设置显示视图,那么flutterView是如何创建的呢,我们分析该语句之前的代码。
我们先来分析第3步骤执行FlutterMain的ensureInitializationComplete方法,先看一下具体实现
public static void ensureInitializationComplete(Context applicationContext, String[] args) { if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException("ensureInitializationComplete must be called on the main thread"); } ... if (sInitialized) { return; } try { sResourceExtractor.waitForCompletion(); List<String> shellArgs = new ArrayList<>(); shellArgs.add("--icu-data-file-path=" + sIcuDataPath); ... String appBundlePath = findAppBundlePath(applicationContext); String appStoragePath = PathUtils.getFilesDir(applicationContext); String engineCachesPath = PathUtils.getCacheDirectory(applicationContext); nativeInit(applicationContext, shellArgs.toArray(new String[0]), appBundlePath, appStoragePath, engineCachesPath); sInitialized = true; } catch (Exception e) { Log.e(TAG, "Flutter initialization failed.", e); throw new RuntimeException(e); } }
我们发现该方法也要求必须在主线程中执行,且只执行一次,一旦执行过会通过sInitialized变量来进行标识下次不再执行。try-catch代码块中第一句sResourceExtractor.waitForCompletion()
表示要等待初始化时的资源初始化完毕后才会向下执行,否则会一直阻塞。下面会初始化一些参数配置信息、flutter打包出的appBundle路径、应用存储目录、引擎缓存目录等信息,然后会调用JNI方法在c++层初始化这些信息,JNI方法对应的c++方法如下
void FlutterMain::Init(JNIEnv* env, jclass clazz, jobject context, jobjectArray jargs, jstring bundlePath, jstring appStoragePath, jstring engineCachesPath) { std::vector<std::string> args; args.push_back("flutter"); for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) { args.push_back(std::move(arg)); } auto command_line = fml::CommandLineFromIterators(args.begin(), args.end()); auto settings = SettingsFromCommandLine(command_line); settings.assets_path = fml::jni::JavaStringToString(env, bundlePath); ... g_flutter_main.reset(new FlutterMain(std::move(settings))); }
c++层会将传入的参数保存到settings对象中,然后根据settings对象创建FlutterMain对象并保存到全局静态变量g_flutter_main
中,供后续flutter引擎初始化使用。
接着,会通过viewFactory创建FlutterView对象,viewFactory就是实现了ViewFactory接口的FlutterActivity对象,查看其createFlutterView方法的实现发现返回null,此时就会执行if中的代码块,同样的,会通过viewFactory创建FlutterNativeView对象,我们查看源码发现同样返回null,这两个方法在FlutterActivity中的实现如下
@Override
public FlutterView createFlutterView(Context context) {
return null;
}
@Override
public FlutterNativeView createFlutterNativeView() {
return null;
}
紧接着,会开始使用FlutterView的带参数的构造方法创建FlutterView对象,其具体实现如下
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) { super(context, attrs); Activity activity = (Activity) getContext(); if (nativeView == null) { mNativeView = new FlutterNativeView(activity.getApplicationContext()); } else { mNativeView = nativeView; } ... mNativeView.attachViewAndActivity(this, activity); mSurfaceCallback = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { assertAttached(); mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface()); } ... }; getHolder().addCallback(mSurfaceCallback); ... // Configure the platform plugins and flutter channels. mFlutterLocalizationChannel = new MethodChannel(this, "flutter/localization", JSONMethodCodec.INSTANCE); ... }
这里参数nativeView上文已经得出结论为null,要先通过FlutterNativeView的构造方法创建mNativeView对象,然后通过mNativeView调用attachViewAndActivity方法将FlutterView和当前的Activity做连接。
接着创建当前FlutterView(要知道它继承自SurfaceView)的mSurfaceCallback对象并添加到当前SurfaceHolder中以监听Surface的变化(如Surface的创建、改变和销毁等),这些变化会执行对应的回调方法,然后通过FlutterJNI的相关方法传递数据给Flutter engine层。
该方法中还会创建各种必要的平台插件和platform channel(用于flutter和原生之间的各种数据传递)。
接下来我们看下FlutterNativeView的构造方法实现
public FlutterNativeView(Context context) {
this(context, false);
}
public FlutterNativeView(Context context, boolean isBackgroundView) {
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
mFlutterJNI = new FlutterJNI();
mFlutterJNI.setRenderSurface(new RenderSurfaceImpl());
mFlutterJNI.setPlatformMessageHandler(new PlatformMessageHandlerImpl());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this, isBackgroundView);
assertAttached();
mMessageHandlers = new HashMap<>();
}
方法中会初始化mFlutterJNI对象&#
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。