转载请注明出处:https://blog.csdn.net/llew2011/article/details/105453204
在前两篇文章 Flutter源码系列之《一》Flutter的热更新探索(上) 和 Flutter源码系列之《一》Flutter的热更新探索(中) 我们分析了Flutter引擎的初始化流程,然后根据启动流程找到了实现热修复的方法,原理就是使用Hook的方式替换系统的FlutterLoader从而实现了代码热修复功能,当时在采用Hook的方式的时候有提到还有其他方式实现热修复功能,今天我们就尝试使用新的方式实现热修复,这篇文章是在前边两篇文章的基础上写的,在阅读这篇文章之前最好有看过前边的两篇文章。
根据前两篇文章的分析我们知道Flutter引擎的加载流程是通过FlutterLoader实现的,具体实现是在startInitialization()方法和ensureInitializationComplete()方法中,第一个方法负责加载Flutter引擎,第二个方法负责给引擎添加配置参数,我们再详细看下给引擎添加配置参数的过程,如下所示:
/**
* Blocks until initialization of the native system has completed.
*
* <p>Calling this method multiple times has no effect.
*
* @param applicationContext The Android application context.
* @param args Flags sent to the Flutter runtime.
*/
public void ensureInitializationComplete(
@NonNull Context applicationContext, @Nullable String[] args) {
if (initialized) {
return;
}
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException(
"ensureInitializationComplete must be called on the main thread");
}
if (settings == null) {
throw new IllegalStateException(
"ensureInitializationComplete must be called after startInitialization");
}
try {
if (resourceExtractor != null) {
resourceExtractor.waitForCompletion();
}
// 创建一个shellArgs集合,添加配置条件,这些配置都是--key=value的形式,最终传递给jni
List<String> shellArgs = new ArrayList<>();
shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
ApplicationInfo applicationInfo = getApplicationInfo(applicationContext);
shellArgs.add("--icu-native-lib-path=" + applicationInfo.nativeLibraryDir + File.separator + DEFAULT_LIBRARY);
// 如果args非空,则把args添加进shellArgs中
if (args != null) {
Collections.addAll(shellArgs, args);
}
String kernelPath = null;
if (BuildConfig.DEBUG || BuildConfig.JIT_RELEASE) {
String snapshotAssetPath =
PathUtils.getDataDirectory(applicationContext) + File.separator + flutterAssetsDir;
kernelPath = snapshotAssetPath + File.separator + DEFAULT_KERNEL_BLOB;
shellArgs.add("--" + SNAPSHOT_ASSET_PATH_KEY + "=" + snapshotAssetPath);
shellArgs.add("--" + VM_SNAPSHOT_DATA_KEY + "=" + vmSnapshotData);
shellArgs.add("--" + ISOLATE_SNAPSHOT_DATA_KEY + "=" + isolateSnapshotData);
} else {
// 这里往shellArgs里边添加了两个配置值,
// 第一个配置是:"--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName
// 第二个配置是:"--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName
// 这两个配置都是以--AOT_SHARED_LIBRARY_NAME=**的方式进行的
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + aotSharedLibraryName);
// Most devices can load the AOT shared library based on the library name
// with no directory path. Provide a fully qualified path to the library
// as a workaround for devices where that fails.
shellArgs.add("--" + AOT_SHARED_LIBRARY_NAME + "=" + applicationInfo.nativeLibraryDir + File.separator + aotSharedLibraryName);
}
shellArgs.add("--cache-dir-path=" + PathUtils.getCacheDirectory(applicationContext));
if (settings.getLogTag() != null) {
shellArgs.add("--log-tag=" + settings.getLogTag());
}
String appStoragePath = PathUtils.getFilesDir(applicationContext);
String engineCachesPath = PathUtils.getCacheDirectory(applicationContext);
// 把shellArgs传递给jni
FlutterJNI.nativeInit(
applicationContext,
shellArgs.toArray(new String[0]),