Flutter WebView 小记
迪丽瓦拉
2024-06-02 15:12:14
0

转载请注明原文链接:
http://t.csdn.cn/3OJpw
https://juejin.cn/post/7209826725366628409

前置条件

Flutter WebView 的更新频率是很快的,也许文中提到的问题,在后面的版本不会有,所以先说明下环境和版本。
此外,使用 WebView 的方式也可能是出现这些异常的因素,使用 FlutterBoost、嵌套、写死高度等。

  • 使用 FlutterBoost 混编版本:4.2.0

  • Flutter 版本:Flutter 3.7.2 • channel stable

  • Dart版本: Dart 2.19.2 • DevTools 2.20.1

  • Flutter Pub:

    • webview_flutter: ^4.0.6
    • webview_flutter_android: ^3.4.2
    • webview_flutter_wkwebview: ^3.2.1
    • webview_flutter_platform_interface: ^2.0.2
  • WebView 嵌套在 Sliver 中:

image.png

image.png

具体问题

  1. 鸿蒙系统、部分oppo、vivo系统,使用 loadHtmlString 加载含图片的本地富文本出现闪退;
  2. 针对 Android 使用 displayWithHybridComposition 的方式加载存在“第二次打开Flutter页时,出现上次 WebView 残留问题“;

问题定位和解决方案

白屏和闪退

  • 定位:因为上述系统都是“阉割版”升级,系统版本升级到了 23 但是 WebView 内核并没有同步到 Google 官方最新版本,直接导致 TextureSurfaceView 崩溃(参考官方文档:texture-layer-hybrid-composition);

  • 解决方案:

    if (WebViewPlatform.instance is WebKitWebViewPlatform) {return WebViewWidget(controller: checkedController);
    } else {return WebViewWidget.fromPlatformCreationParams(params: AndroidWebViewWidgetCreationParams(controller: checkedController.platform,//针对鸿蒙系统使用 displayWithHybridComposition 为 truedisplayWithHybridComposition: Constants.isHarmony,),);// return AndroidWebViewWidget(//   AndroidWebViewWidgetCreationParams(//     controller: checkedController.platform,//     displayWithHybridComposition: true,//   ),// ).build(context);
    }
    

残留或内存没有释放

  • 定位:这一点没有找到官方解释,有可能是 FlutterBoost 影响了生命周期导致没有释放,也有可能是使用 displayWithHybridComposition 时,Android WebView 是一个单例,也许两者都有,总之是暂未有定论。(之前看到 FlutterBoost 更新说明提到: [Android] Fixes HybridCompositon does not work (#1743),然并卵)

  • 解决方案:(有两个思路)

    • WebView 是单例,那么针对使用Hybird的情况,在每个Flutter页面初始化一个空的 WebView 就可以去掉残留(这个是个坏的解决方案)。

    • 使用 WebViewFlutterAndroidExternalApi ,在原生端获取到Flutter端的WebView,在 Activity onDesroty 时释放 WebView,如下:

      override fun onDestroy() {Ulog.i("ToFlutterContainerActivity onDestroy in")
      //exclusiveAppComponent?.FlutterNativeBridge.mEngine?.also { flutterEngine ->FlutterNativeBridge.invokeFlutterWebViewIdentifierList { webViewIds ->webViewIds.forEach { identifier ->WebViewFlutterAndroidExternalApi.getWebView(flutterEngine, identifier)?.also { webView ->ULog.i("ToFlutterContainerActivity in webView.destroy: $identifier")// webView.destroy()if(webView.parent is ViewGroup){ULog.i("ToFlutterContainerActivity in webView.removeView: $identifier")(webView.parent as ViewGroup).removeView(webView)webView.destroy()}}}}}super.onDestroy()
      }
      

小结

有两个点

一个是混编如果可以最好用官方的试试,FlutterBoost 不太放心,而且存在很多和官方设计思维不太匹配的问题;

一个是 WebView 的嵌套实现,由于时间问题,其实不应该这么简单的计算方式,可以试试这个extended_sliver的思路

相关内容