背景
工程使用了混合开发,使用flutter boost插件,flutter 的activity1 frament1 跳转activity2 frament2,frament1 包含platformView,按照上面老哥解决崩溃问题的基础上,出现activity2 frament2返回activity1 frament1时,platformView触摸事件没有响应。问题具体见:https://github.com/alibaba/flutter_boost/issues/1755
分析
项目主页使用platview实现了webview功能,即ctivity1 frament1为主页。具体见下图所示
使用AndroidView,flutter3.7上底层使用PlatformViewWrapper作为容器,底层事件是先被PlatformViewWrapper接收,在onTouchEvent中分发到Dart,然后到dart层,然后再分发到PlatformViewsController分发到platformView,具体见:Flutter 之快速理解混合开发里的手势事件传递 - 掘金
调试时,发现activity2 frament2返回时,在activity1 frament1 已经在PlatformViewsController已经attach,activity2的onDestroy触发flutterboostfragment的onDetach,最终调用了PlatformViewsController又执行一次detach方法,导致platformViewsChannel被置为空,触摸事件没法传递过来
/**
- Detaches this platform views controller.
-
This is typically called when a Flutter applications moves to run in the background, or is
- destroyed. After calling this the platform views controller will no longer listen to it's
- previous messenger, and will not maintain references to the texture registry, context, and
- messenger passed to the previous attach call.
*/
@UiThread
public void detach() {
if (platformViewsChannel != null) {
platformViewsChannel.setPlatformViewsHandler(null);
}
destroyOverlaySurfaces();
platformViewsChannel = null;
context = null;
textureRegistry = null;
}
解决
把platformViewsChannel重新attach,恢复platformViewsChannel,能让activity1 frament1 的platformView重新获取触摸事件。
实现:
activity2的onDestroy时,异步去调用 flutterEngine.getPlatformViewsController().attach(getContextActivity(), flutterEngine.getRenderer(), flutterEngine.getDartExecutor()); 前提是判断frament1处于可见状态,且处于detach状态
兼容:
PlatformViewsController在attach时有个判断context是否为空,如下所示:
public void attach(
@nullable Context context,
@nonnull TextureRegistry textureRegistry,
@nonnull DartExecutor dartExecutor) {
if (this.context != null) {
throw new AssertionError(
"A PlatformViewsController can only be attached to a single output target.\n"
+ "attach was called while the PlatformViewsController was already attached.");
}
this.context = context;
this.textureRegistry = textureRegistry;
platformViewsChannel = new PlatformViewsChannel(dartExecutor);
platformViewsChannel.setPlatformViewsHandler(channelHandler);
}
因此在上面老哥重写的FlutterBoostPlatformViewsController中覆盖attach方法添加detach()下兼容处理,避免快速切换,context不为空的AssertionError问题
@OverRide
public void attach(
@nullable Context context,
@nonnull TextureRegistry textureRegistry,
@nonnull DartExecutor dartExecutor) {
//fixMe super.attach里面需要context为空,否则直接抛异常,而在生命周期里面设置会因为快速点击不够实时设置导致异常
//因此,在attach之前先重置下,当官方解决问题可以移除这个代码
detach();
super.attach(context,textureRegistry,dartExecutor);
}