这个类的主要作用就是同步activity 和Flutter的生命周期
@Override
public void onCreate() {
//....
mState = STATE_CREATED;
mContainer.getBoostFlutterView().onResume();
mProxy.create();
}
@Override
public void onAppear() {
//....
mState = STATE_APPEAR;
mManager.pushRecord(this);
mContainer.getBoostFlutterView().onAttach();
mProxy.appear();
}
@Override
public void onDisappear() {
//....
mState = STATE_DISAPPEAR;
mProxy.disappear();
if(getContainer().getContextActivity().isFinishing()) {
mProxy.destroy();
}
mContainer.getBoostFlutterView().onDetach();
mManager.popRecord(this);
}
@Override
public void onDestroy() {
//....
mState = STATE_DESTROYED;
mProxy.destroy();
mContainer.getBoostFlutterView().onDestroy();
mManager.removeRecord(this);
mManager.setContainerResult(this,-1,-1,null);
if (!mManager.hasContainerAppear()) {
mContainer.getBoostFlutterView().onPause();
mContainer.getBoostFlutterView().onStop();
}
}
//....其他的生命周期
同步的生命周期主要有onAppear/onDisappear/onDestroy 等
还有一个就是methodProxy 通信代理类,告知flutter页面的生命周期的回调
private class MethodChannelProxy {
private int mState = STATE_UNKNOW;
private void create() {
if (mState == STATE_UNKNOW) {
invokeChannelUnsafe("didInitPageContainer",
mContainer.getContainerUrl(),
mContainer.getContainerUrlParams(),
mUniqueId
);
mState = STATE_CREATED;
}
}
public void invokeChannelUnsafe(String method, String url, Map params, String uniqueId) {
HashMap args = new HashMap<>();
args.put("pageName", url);
args.put("params", params);
args.put("uniqueId", uniqueId);
FlutterBoost.singleton().channel().invokeMethodUnsafe(method, args);
}
}
//其他页面生命周期的回调......
public static String genUniqueId(Object obj) {
return System.currentTimeMillis() + "-" + obj.hashCode();
}
之后总体会调用到BoostChannel类中的invokeMethodUnsafe/invokeMethod方法中
public void invokeMethodUnsafe(final String name,Serializable args){
invokeMethod(name, args, new MethodChannel.Result() {
@Override
public void success(@Nullable Object o) {
//every thing ok...
}
@Override
public void error(String s, @Nullable String s1, @Nullable Object o) {
Debuger.log("invoke method "+name+" error:"+s+" | "+s1);
}
@Override
public void notImplemented() {
Debuger.log("invoke method "+name+" notImplemented");
}
});
}
对应的APP整体的声明周期回调是通过Application.ActivityLifecycleCallbacks 这个回调函数来确认的
FlutterBoost构造函数注册了这个回调函数
具体代码如下
class ActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityStarted(Activity activity) {
if (mCurrentActiveActivity == null) {
if (mEngineProvider.tryGetEngine() != null) {
HashMap map = new HashMap<>();
map.put("type", "foreground");
channel().sendEvent("lifecycle",map);
}
}
mCurrentActiveActivity = activity;
}
//....其他APP生命周期回调
}
通过上面的invokeMethod会通过Channel调用到Flutter对应的boost_channel.dart对应的方法中
typedef Future EventListener(String name, Map arguments);
typedef Future MethodHandler(MethodCall call);
class BoostChannel {
final MethodChannel _methodChannel = MethodChannel("flutter_boost");
final Map> _eventListeners = Map();
final Set _methodHandlers = Set();
BoostChannel() {
_methodChannel.setMethodCallHandler((MethodCall call){
if (call.method == "__event__") {
//取出对应的参数
String name = call.arguments["name"];
Map arg = call.arguments["arguments"];
List list = _eventListeners[name];
if (list != null) {
for (EventListener l in list) {
//App生命周期 循环调用给回调函数
l(name, arg);
}
}
}else{
for(MethodHandler handler in _methodHandlers) {
//页面Page生命周期 循环调用给回调函数
handler(call);
}
}
return Future.value();
});
}
}
执行回调是FlutterBoost的构造函数调用ContainerCoordinator(_boostChannel)之后进入到了container_coordinator.dart中
ContainerCoordinator(BoostChannel channel) {
assert(_instance == null);
_instance = this;
channel.addEventListener("lifecycle",
(String name, Map arguments) => _onChannelEvent(arguments));
channel.addMethodHandler((MethodCall call) => _onMethodCall(call));
}
Future _onChannelEvent(dynamic event) {
if (event is Map) {
Map map = event;
final String type = map['type'];
switch (type) {
case 'foreground':
{
FlutterBoost.containerManager?.setForeground();
}
break;
//....其他App生命周期回调处理
}
}
}
Future _onMethodCall(MethodCall call) {
switch (call.method) {
case "didInitPageContainer":
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerDidInit(pageName, params, uniqueId);
}
break;
//....其他页面生命周期回调处理
}
}
主要是体现在XFlutterView 的attachToFlutterEngine和detachFromFlutterEngine方法中
public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
Log.d(TAG, "attachToFlutterEngine()");
if (isAttachedToFlutterEngine()) {
if (flutterEngine == this.flutterEngine) {
// 相同 复用之前的引擎
return;
}
// 不同 移除之前的引擎
detachFromFlutterEngine();
}
//重新赋值
this.flutterEngine = flutterEngine;
// 设置渲染层
this.flutterEngine.getRenderer().attachToRenderSurface(renderSurface);
// 重设输入输出
textInputPlugin = new TextInputPlugin(
this,
this.flutterEngine.getDartExecutor()
);
//android 的键盘处理
androidKeyProcessor = new AndroidKeyProcessor(
this.flutterEngine.getKeyEventChannel(),
textInputPlugin
);
//触摸处理
androidTouchProcessor = new AndroidTouchProcessor(this.flutterEngine.getRenderer());
//辅助连接桥
accessibilityBridge = new AccessibilityBridge(
this,
flutterEngine.getAccessibilityChannel(),
(AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE),
getContext().getContentResolver(),
// TODO(mattcaroll): plumb the platform views controller to the accessibility bridge.
// https://github.com/flutter/flutter/issues/29618
null
);
accessibilityBridge.setOnAccessibilityChangeListener(onAccessibilityChangeListener);
resetWillNotDraw(
accessibilityBridge.isAccessibilityEnabled(),
accessibilityBridge.isTouchExplorationEnabled()
);
//重启输入连接
textInputPlugin.getInputMethodManager().restartInput(this);
//一系列初始化
// Push View and Context related information from Android to Flutter.
sendUserSettingsToFlutter();
sendLocalesToFlutter(getResources().getConfiguration());
sendViewportMetricsToFlutter();
}
public void detachFromFlutterEngine() {
if (!isAttachedToFlutterEngine()) {
return;
}
//重启输入连接
textInputPlugin.getInputMethodManager().restartInput(this);
// 移除渲染层
flutterEngine.getRenderer().detachFromRenderSurface();
flutterEngine = null;
}
引擎相同则复用,不同detach 之前,重新赋值以及初始化相关的配置
调用链 PageRouter.openPageByUrl -->BoostFlutterEngine.startRun -->BoostFlutterActivity.onCreate -->createFlutterView(mFlutterEngine)
BoostFlutterEngine.startRun这个方法的启动主要是在Application 配置的启动的方式来决定的
int IMMEDIATELY = 0; //立即启动引擎
int ANY_ACTIVITY_CREATED = 1; //当有任何Activity创建时,启动引擎
@Override
public int whenEngineStart() {
return ANY_ACTIVITY_CREATED;
}
默认使用这个ANY_ACTIVITY_CREATED 的时候,会在ActivityLifecycleCallbacks回调函数中做处理
class ActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (platform().whenEngineStart() == IPlatform.ANY_ACTIVITY_CREATED) {
sInstance.mEngineProvider
.provideEngine(activity)
.startRun(activity);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
configureWindowForTransparency();
//创建同步器
mSyncer = FlutterBoost.singleton().containerManager().generateSyncer(this);
//创建引擎
mFlutterEngine = createFlutterEngine();
//创建FlutterView
mFlutterView = createFlutterView(mFlutterEngine);
setContentView(mFlutterView);
//同步器初始化
mSyncer.onCreate();
//配置状态栏
configureStatusBarForFullscreenFlutterExperience();
}
同步器就是前面讲的ContainerRecord,主要是同步Flutter和Android的页面和APP状态
FlutterEngine,这个是Flutter的核心,flutter_boost对其做了进一步的封装
FlutterView 主要是展示Flutter中的Widget页面
主要是修改DartExecutor.DartEntrypoint和 InitRoute 以及对应的插件注册
public BoostFlutterEngine(@NonNull Context context, DartExecutor.DartEntrypoint entrypoint, String initRoute) {
super(context);
mContext = context.getApplicationContext();
mBoostPluginRegistry = new BoostPluginRegistry(this, context);
//支持用户的修改的进入点 一般对应的main
if (entrypoint != null) {
mEntrypoint = entrypoint;
} else {
mEntrypoint = defaultDartEntrypoint(context);
}
//初始化路由
if (initRoute != null) {
mInitRoute = initRoute;
} else {
mInitRoute = defaultInitialRoute(context);
}
//获取FlutterJNI用于引擎通信相关的
FlutterJNI flutterJNI = null;
try {
Field field = FlutterEngine.class.getDeclaredField("flutterJNI");
field.setAccessible(true);
flutterJNI = (FlutterJNI) field.get(this);
} catch (Throwable t) {
try {
for(Field field:FlutterEngine.class.getDeclaredFields()) {
field.setAccessible(true);
Object o = field.get(this);
if(o instanceof FlutterJNI) {
flutterJNI = (FlutterJNI)o;
}
}
if(flutterJNI == null) {
throw new RuntimeException("FlutterJNI not found");
}
}catch (Throwable it){
Debuger.exception(it);
}
}
mFakeRender = new FakeRender(flutterJNI);
}
BoostRegistrar 插件注册主要是获取Activity,让Container 和Activity同步
@Override
public Activity activity() {
Activity activity;
IContainerRecord record;
//获取当前的Container
record = FlutterBoost.singleton().containerManager().getCurrentTopRecord();
if (record == null) {
//获取最后生成Container
record = FlutterBoost.singleton().containerManager().getLastGenerateRecord();
}
if (record == null) {
activity = FlutterBoost.singleton().currentActivity();
} else {
activity = record.getContainer().getContextActivity();
}
if (activity == null && mCurrentActivityRef != null) {
activity = mCurrentActivityRef.get();
}
if (activity == null) {
throw new RuntimeException("current has no valid Activity yet");
}
return activity;
BoostFlutterView主要是封装各种Flutter需要加载的东西
private void init() {
//创建引擎
if (mFlutterEngine == null) {
mFlutterEngine = createFlutterEngine(getContext());
}
//activity传递的参数
if (mArguments == null) {
mArguments = new Bundle();
}
//FlutterBoost平台自身需要的参数
mPlatformPlugin = new PlatformPlugin((Activity) getContext(), mFlutterEngine.getPlatformChannel());
//封装的XFlutterView
mFlutterView = new XFlutterView(getContext(), getRenderMode(), getTransparencyMode());
//添加控件
addView(mFlutterView, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//截屏View
mSnapshot = new SnapshotView(getContext());
//Flutter引擎初始化loading
if(mRenderingProgressCoverCreator != null) {
mRenderingProgressCover = mRenderingProgressCoverCreator
.createRenderingProgressCover(getContext());
}else{
mRenderingProgressCover = createRenderingProgressCorver();
}
//添加loading
if(mRenderingProgressCover != null) {
addView(mRenderingProgressCover, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
//监听第一帧绘制回调函数
mFlutterView.addOnFirstFrameRenderedListener(mOnFirstFrameRenderedListener);
//启动封装引擎
mFlutterEngine.startRun((Activity)getContext());
final IStateListener stateListener = FlutterBoost.sInstance.mStateListener;
if(stateListener != null) {
stateListener.onFlutterViewInited(mFlutterEngine,this);
}
checkAssert();
}
默认的createRenderingProgressCorver返回的是一个ProgressBar 用户可以根据重写这个方法自己修改loading界面
还有一些相关的类 XAndroidKeyProcessor(按键处理)/XInputConnectionAdaptor(输入输出适配)/XTextInputPlugin(输入插件)。总体来讲,flutter_boost的Android版本插件难度不是很大,Flutter Page/App生命周期同步以及引擎封装思路还是不错的,可以像WebView一样的使用是该插件的初衷。以后有时间还有进一步的解读源码。