Flutter - FlutterActivity, 咱照葫芦画瓢
背景
由于历史原因,有一个老项目中使用了Flutter代码作为插件使用,但是也遗留了一个历史问题。先说明下这个问题:
首先我很早之前编写了一个BaseFlutterActivity类,是继承于AppCompatActivity的,其中它的子类的使用即是一个Activity对应一个Flutter的页面,是一对一的关系,并且只能一对一关系。但是现在我想把它弄成一个Activity对应N个Flutter页面,问题就来了,原来的Activity并不能处理页面的返回事件。
头疼,但是也不能改之前的代码,不然会影响太多太多的Activity。那就“照葫芦画瓢”吧。想想,SDK中提供的FlutterActivity支持页面返回事件处理,那就复制它的代码吧。
复制SDK中提供的FlutterActivity的代码
- 需要按照它的实现某些接口 FlutterView.Provider, PluginRegistry, FlutterActivityDelegate.ViewFactory;
- 注意合适的位置注册Plugin,包括自定义的和系统自动生成插件方法(GeneratedPluginRegistrant.registerWith(pluginRegistry) );
- 注意处理各种生命周期和事件--事件重写和调用;
注意:
- 方法createFlutterView我重新实例化了一个FlutterView,这里是为了方便使用setInitialRoute, 如果不这么做,系统会自己调用默认的路由路径。
- 在调用这个自定义的FlutterActivity之前,需要先调用 ** FlutterMain.startInitialization(this); **,不然程序可能会闪退。
现在咱可以在这个Activity中使用ViewProvider做网络调用支援,也可以在MethodChannel做一些需要的相互调用的操作。
:-) 此处做个记录,防止忘记和再次踩坑!
open class BaseFlutterActivity() : AppCompatActivity(), FlutterView.Provider,
PluginRegistry,
FlutterActivityDelegate.ViewFactory {
companion object {
@JvmField
val TAG = "FlutterActivity"
/** 通讯频道名称 **/
const val DefaultChannelName = "plugins.cosecant.flutter/page-assistant"
/** 路由名称 **/
const val ArgRouteName = "routeName"
/**
* 打开Flutter页面
* @param context 上下文对象
* @param routeName Flutter路由名称, 默认为:default
*/
@JvmStatic
fun start(context: Context, routeName: String = "default") = with(Bundle()) {
putString(ArgRouteName, routeName)
Router.forward(context, BaseFlutterActivity::class.java, data = this)
}
}
private val delegate by lazy { FlutterActivityDelegate(this, this) }
// These aliases ensure that the methods we forward to the delegate adhere
// to relevant interfaces versus just existing in FlutterActivityDelegate.
private val eventDelegate: FlutterActivityEvents = delegate
private val viewProvider: FlutterView.Provider = delegate
private val pluginRegistry: PluginRegistry = delegate
/** 默认路由名称 **/
protected open val activityRouteName = "default"
/** 传递过来的路由名称 **/
private val routeName by lazy {
when {
intent?.hasExtra(ArgRouteName) == true -> intent.getStringExtra(ArgRouteName)
?: activityRouteName
intent?.extras?.containsKey(ArgRouteName) == true -> intent?.extras?.getString(
ArgRouteName
)
?: activityRouteName
else -> activityRouteName
}
}
/** method-channel **/
protected var methodChannel: MethodChannel? = null
override fun retainFlutterNativeView(): Boolean = false
override fun createFlutterNativeView(): FlutterNativeView? = null
override fun createFlutterView(context: Context?): FlutterView? = FlutterView(this).apply {
setInitialRoute(routeName) //设置初始路径
//注册插件
GeneratedPluginRegistrant.registerWith(pluginRegistry)
BarcodeProviderPlugin.registerWith(pluginRegistry)
ZxingBarPluginRegistrant.registerWith(pluginRegistry)
EnvironmentProviderPlugin.registerWith(pluginRegistry)
addFirstFrameListener { onFlutterViewAttached() }
layoutParams = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
setContentView(this)
}
override fun getFlutterView(): FlutterView = viewProvider.flutterView
override fun valuePublishedByPlugin(pluginKey: String?): T =
pluginRegistry.valuePublishedByPlugin(pluginKey)
override fun registrarFor(pluginKey: String?): Registrar =
pluginRegistry.registrarFor(pluginKey)
override fun hasPlugin(pluginKey: String?): Boolean = pluginRegistry.hasPlugin(pluginKey)
@Override
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
eventDelegate.onCreate(savedInstanceState)
initView() //初始化视图
EventBus.getDefault().register(this)
}
/** 初始化视图 **/
protected open fun initView() {
initMethodChannel() //初始化MethodChannel
}
/** 初始化MethodChannel **/
protected open fun initMethodChannel() {
methodChannel = MethodChannel(flutterView, DefaultChannelName)
methodChannel?.setMethodCallHandler { methodCall, result ->
onHandleMethodChannelInvoke(methodCall, result)
}
}
/** 此方法中在FlutterView加载完毕并显示第一贴的时候调用 **/
protected open fun onFlutterViewAttached() {}
/**
* 处理MethodChannel回调
* @param methodCall 方法回调参数
* @param result 结果处理
*/
protected open fun onHandleMethodChannelInvoke(
methodCall: MethodCall?,
result: MethodChannel.Result?
) {
when (methodCall?.method) {
"finish" -> { //关闭当前页面
goBack()
result?.success(null)
}
}
}
override fun onStart() {
super.onStart()
eventDelegate.onStart()
}
override fun onResume() {
super.onResume()
eventDelegate.onResume()
}
override fun onDestroy() {
eventDelegate.onDestroy()
super.onDestroy()
}
override fun onBackPressed() {
if (!eventDelegate.onBackPressed()) {
super.onBackPressed()
}
}
override fun onStop() {
eventDelegate.onStop()
super.onStop()
}
override fun onPause() {
super.onPause()
eventDelegate.onPause()
}
override fun onPostResume() {
super.onPostResume()
eventDelegate.onPostResume()
}
// @Override - added in API level 23
override fun onRequestPermissionsResult(requestCode: Int, @NonNull permissions: Array, @NonNull grantResults: IntArray) {
eventDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
if (!eventDelegate.onActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data)
}
}
@SuppressLint("MissingSuperCall")
override fun onNewIntent(intent: Intent?) {
eventDelegate.onNewIntent(intent)
}
override fun onUserLeaveHint() {
eventDelegate.onUserLeaveHint()
}
override fun onTrimMemory(level: Int) {
eventDelegate.onTrimMemory(level)
}
override fun onLowMemory() {
eventDelegate.onLowMemory()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
eventDelegate.onConfigurationChanged(newConfig)
}
/** 页面返回 **/
protected open fun goBack(): Unit =
Router.back(this, enterAnimRes = R.anim.slide_in_left, exitAnimRes = R.anim.slide_out_right)
}