以下说明均基于io.flutter.embedding包下的flutter类
关于flutterengine和flutterview:
flutter界面用flutterengine加载,flutter界面用flutterview展示。
Engine使用前需要调用getDartExecutor().executeDartEntrypoint预热,设置initialRoute只能在预热之前(initialRoute是string类型,可用于传递初始化信息给flutter模块)。
一个engine只能加载一次flutter界面,且同一时间同一个engine加载的界面只能显示在一个fluterview上面.(flutterview调用attachToFlutterEngine依附于engine从而显示engine加载的界面,同一个engine的界面只会显示在最后一个调用attachToFlutterEngine的flutterview上面)。
FlutterEngine flutterEngine =new FlutterEngine(this);
//初始化路由信息
flutterEngine.getNavigationChannel().setInitialRoute("test");
//预热
flutterEngine.getDartExecutor().executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault());
FlutterView flutterView =new FlutterView(this);
flutterView.attachToFlutterEngine(flutterEngine);
关于flutteractivity:
flutteractivity使用一个flutterview来作为“ContentView”。
一个flutteractivity需要一个flutterengine来加载flutter界面,可以指定activity初始化flutterengine的模式:使用缓存或新建。
缓存模式:需要事先初始化一个engine并放入FlutterEngineCache的map中,并将key值传给flutteractivity,再由flutteractivity根据key值从FlutterEngineCache中取出来,请注意如果key值对应的engine并没有在cache中找到,那么会抛异常,所以使用缓存模式一定要事先初始化一个engine,该模式适用于展示一些常用页面。
FlutterEngineCache.getInstance().put("key",flutterEngine);
Intent intent = io.flutter.embedding.android.FlutterActivity.withCachedEngine("key").build(this);
startActivity(intent);
新建模式:每次都会新建一个engine,跟activity的standard启动模式类似。
Intent intent = io.flutter.embedding.android.FlutterActivity.withNewEngine().initialRoute("test").build(this);
startActivity(intent);
注意:FlutterEngineCache是非线程安全的单例模式,且内部的map也是非线程安全的hashmap,所以请确保在单一线程中使用cache。
关于flutterfragment:
与flutteractivity类似。
关于自定义flutteractivity:
如果仅是直接使用flutteractivity或者flutterfragment,知道以上信息已足够。若要自定义使用flutter的activity(不继承flutteractivity)来使用,请注意以下几点。
flutterengine内置有一个ActivityControlSurface实例,主要用来处理activity的onactivityresult、onnewintent等回调函数,官方源码的使用方法如下:
首先,在activity的oncreate时,flutterengine需要调用getActivityControlSurface().attachToActivity来使ActivityControlSurface依附于activity。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//getEngine()为自定义的获取engine的方法
getEngine().getActivityControlSurface().attachToActivity(this, getLifecycle());
}
在activity的onDestroy()时,需分两种情况,一种是activity真的销毁,这时需调用ActivityControlSurface的detachFromActivity(),另一种是屏幕旋转等ConfigChanges带来的销毁,这时调用detachFromActivityForConfigChanges()。
@Override
protected void onDestroy() {
super.onDestroy();
/*...dosomething*/
if (isChangingConfigurations()) {
getEngine().getActivityControlSurface().detachFromActivityForConfigChanges();
}else {
getEngine().getActivityControlSurface().detachFromActivity();
}
}
在activity的onactivityresult、onnewintent等方法里面还需要手动调用ActivityControlSurface的相应方法,以此来让flutter处理onactivityresult、onnewintent等。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
getEngine().getActivityControlSurface().onActivityResult(requestCode, resultCode, data);
}
除此之外,在activity onresume、onpause、onstop、ondestory时,flutterengine需用内置的lifecyclechannel来手动分别调用appIsResumed()、appIsInactive、appIsPaused、appIsDetached以通知flutter界面进入相应状态,如果不使用这些flutter界面将无法正常展示。
@Override
protected void onResume() {
super.onResume();
/*...dosomething*/
getEngine().getLifecycleChannel().appIsResumed();
}
@Override
protected void onPause() {
super.onPause();
/*...dosomething*/
getEngine().getLifecycleChannel().appIsInactive();
}
@Override
protected void onDestroy() {
super.onDestroy();
/*...dosomething*/
getEngine().getLifecycleChannel().appIsDetached();
}
小结:
基于此,自定义flutteractivity适用于即有原生界面又有flutter界面、或者flutter界面需要与原生实时交互的场景,需开发者同时调控原生界面和flutter界面的生命周期和相关回调。官方flutteractivity只能展示flutter界面,如果一个界面仅需要有flutter界面,使用它准没错。
关于flutter与android进行实时交互需通过MethodChannel、MessageChannel等channel来进行,这个之后再做探讨。