Flutter未清除已渲染组件仅重绘 出现阴影残影弹窗不消失问题
Flutter InAppWebView上层组件残留阴影、弹窗不消失异常修复
问题现象
- 页面基于Scaffold实现,配置floatingActionButton悬浮控件,页面内嵌入InAppWebView加载网页,floatingActionButton悬浮显示在WebView上层,页面支持短暂弹出提示类弹窗
- 升级Flutter版本后突发异常,降级回原版本后问题未消失:所有渲染在上层的组件始终不会被系统清除,仅持续执行重绘,最终导致组件周围出现深色阴影、弹出的弹窗永久不消失
- 具体异常表现:floatingActionButton和底部栏周围出现明显深色阴影,页面临时弹出的
<3 + Karma标识无法正常消失 - 问题特殊性:未修改任何项目代码,另一台开发设备使用完全相同的代码、pubspec.yaml依赖版本、一致的Flutter/Dart版本构建应用时运行完全正常,仅主力开发机构建的应用存在该bug,无法打包可用新版本
当前使用的Flutter版本信息:
Flutter 2.10.2 • channel unknown • unknown source Framework • revision 097d3313d8 (3 months ago) • 2022-02-18 19:33:08 -0600 Engine • revision a83ed0e5e3 Tools • Dart 2.16.1 • DevTools 2.9.2
- 执行
flutter doctor命令检测结果为No issues found!,未检测到环境问题
异常截图:
问题页面参考代码:
return WillPopScope( onWillPop: ArticleHandler().backButtonPressed, child: Scaffold( floatingActionButton: Visibility( visible: _fabIsVisible, child: FloatingActionButton( onPressed: () { webView.scrollTo(x: 0, y: 0, animated: true); }, child: Icon( Icons.arrow_upward, color: Colors.white, ), backgroundColor: Theme.of(context).primaryColor, )), floatingActionButtonLocation: MarginEndFloatFABLocation(), floatingActionButtonAnimator: NoFABAnimation(), appBar: TopBar(widget.articlePreview.url), body: Builder(builder: (BuildContext context) { return Container( child: Column( children: <Widget>[ progress < 1.0 ? Container( height: 3, child: LinearProgressIndicator( value: progress, backgroundColor: Colors.white, valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).primaryColor), )) : Container(height: 0), Expanded( child: InAppWebView( initialOptions: InAppWebViewGroupOptions( android: AndroidInAppWebViewOptions(useHybridComposition: true), crossPlatform: InAppWebViewOptions( //cacheEnabled: false, // uncomment this line to clean cache on open )), onWebViewCreated: (InAppWebViewController controller) { webView = controller; }, onProgressChanged: (InAppWebViewController controller, int progress) { setState(() { this.progress = progress / 100; }); }, onOverScrolled: (InAppWebViewController controller, int x, int y, bool clampedX, bool clampedY) { // maybe show karma badge }, onScrollChanged: (InAppWebViewController controller, int x, int y) async { if (y > 0) { if (!_fabIsVisible) { setState(() { _fabIsVisible = true; }); } } else { if (_fabIsVisible) { setState(() { _fabIsVisible = false; }); } } })), BottomTagBar(), ], )); }), ));
问题原因
核心诱因为主力开发机构建缓存污染叠加Android平台WebView混合渲染冲突,和业务代码本身无关:
- 升级Flutter时未执行全量缓存清理,降级回旧版本后,项目build目录的渲染中间产物、Android端Gradle构建缓存残留了新版本的渲染管线配置,导致PlatformView图层合成逻辑异常。叠加在WebView上层的Flutter组件在被标记为隐藏/移除时,GPU未执行正常清屏操作,每帧重绘时透明度不断叠加,最终形成深色阴影、临时组件永久残留的现象。
- 代码中开启了
useHybridComposition: true混合组合模式,该模式下WebView会被渲染为独立的Android原生View,Flutter图层合成逻辑一旦出现缓存异常,就会触发上层Flutter组件图层无法正常回收的问题。 - 另一台开发设备运行正常,是因为该设备未经历过Flutter版本升降级操作,不存在构建缓存污染问题。
修复方案
按顺序执行以下操作即可解决问题:
- 清理Flutter项目构建缓存,在项目根目录执行命令:
flutter clean flutter pub get
- 清理Android端Gradle构建缓存,进入项目android目录执行命令:
cd android ./gradlew clean cd ..
- 卸载测试设备上已安装的旧版本安装包,清除设备端的应用残留数据。
- 如果上述操作后问题仍存在,删除Flutter SDK安装目录下的
bin/cache文件夹,重新执行flutter doctor等待SDK自动补全缓存后,再重新构建项目。 - 问题定位可选方案:可临时修改InAppWebView的Android配置,关闭混合组合模式验证渲染逻辑是否恢复:
android: AndroidInAppWebViewOptions(useHybridComposition: false),
注意:关闭混合组合模式会导致WebView部分手势交互能力、渲染性能下降,仅用于临时问题定位,不建议作为最终修复方案。
内容的提问来源于stack exchange,提问作者progNewbie
相关产品推荐
相关产品推荐

