转载请注明出处:https://blog.csdn.net/llew2011/article/details/104075796
在Google发布Flutter之后我一直对它保持很高的热情,尤其是Flutter支持热更新,但在1.7.8版本之后由于某些原因Google屏蔽了热更新功能,这着实让让人失落……于是抽了点时间研究了一下Flutter的加载过程,目的是找到可以实现热更新的方式,在阅读文章之前需要小伙伴们对Flutter的编译模式有一定了解,目前我使用的Flutter版本为dev分支的1.14.0,Dart版本为2.8.0,如下所示:
要实现Flutter的热更新功能就要先弄清楚Flutter的加载流程,比如Flutter引擎什么时机加载,引擎加载完毕后libapp.so文件什么时机加载等,因此我们先分析一下Flutter的加载过程。
首先新建Flutter项目flutter_hotfix,然后运行该项目,如下所示:
项目启动后运行如上所示,页面上展示了一个文案和计数器数值,点击+
按钮计数器的值就会自增。接下来我们看下在Manifest中配置的启动信息,打开AndroidManifext.xml
文件,如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.llew.flutter.flutter_hotfix">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_hotfix"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Manifest默认配置了当前项目的Application为FlutterApplication
,启动页面是MainActivity
,另外配置的meta-data信息我们先不关注,我们先看FlutterApplication
类(在flutter.jar包中),如下所示:
public class FlutterApplication extends Application {
@Override
@CallSuper
public void onCreate() {
super.onCreate();
FlutterMain.startInitialization(this);
}
private Activity mCurrentActivity = null;
// 省略set/get方法
}
FlutterApplication
继承Application,它定义了Activity类型的mCurrentActivity属性并给其添加了set/get方法,另外FlutterApplication
重写了onCreate()方法,在onCreate()方法中仅调用了FlutterMain的startInitialization()静态方法进行初始化操作,FlutterMain源码如下:
public class FlutterMain {
/**
* Starts initialization of the native system.
* @param applicationContext The Android application context.
*/
public static void startInitialization(@NonNull Context applicationContext) {
if (isRunningInRobolectricTest) {
return;
}
FlutterLoader.getInstance().startInitialization(applicationContext);
}
/**
* Starts initialization of the native system.
* <p>
* This loads the Flutter engine's native library to enable subsequent JNI calls. This also
* starts locating and unpacking Dart resources packaged in the app's APK.
* <p>
* Calling this method multiple times has no effect.
*
* @param applicationContext The Android application context.
* @param settings Configuration settings.
*/
public static void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
if (isRunningInRobolectricTest) {
return;
}
FlutterLoader.Settings newSettings = new FlutterLoader.Settings();
newSettings.setLogTag(settings.getLogTag());
FlutterLoader.getInstance().startInitialization(applicationContext, newSettings);
}
// 省略相关代码
}
FlutterMain定义了一系列静态方法,而这些方法内部又委托FlutterLoader实现具体功能,FlutterLoader看名字就知道是一个加载类,它可能是我们实现热更新的入口类。FlutterLoader对外提供了一个静态的getInstance()方法便于获取其实例(该方法是单例的),其startInitialization()源码如下:
public class FlutterLoader {
private static final String TAG = "FlutterLoader";
// 省略部分属性
private static FlutterLoader instance