Flutter应用切后台返回后InAppWebView冻结无响应问题
问题根因
- 核心故障来自
flutter_inappwebview在Android端开启HybridComposition渲染模式时的生命周期适配缺陷:应用切至后台停留数秒后,系统会回收WebView绑定的渲染Surface,切回前台时WebView未正确重建渲染层,直接导致渲染线程、输入事件队列阻塞,表现为页面冻结、网页无法滚动,甚至Flutter原生控件也无响应,必须杀进程重启才能恢复。 - 现有代码存在逻辑bug:
shouldOverrideUrlLoading回调中判断外链跳转时,错误引用了全局url变量,而非当前导航行为携带的目标地址,会导致外链跳转逻辑异常,极端场景下会触发路由死锁。 - 代码未实现应用生命周期监听,切后台再恢复的场景下没有主动触发WebView的状态重置。
修复步骤
- 修复外链跳转逻辑错误
找到shouldOverrideUrlLoading回调内的判断逻辑,将错误的全局url变量替换为当前导航的目标地址,修正后代码如下:shouldOverrideUrlLoading: (controller, navigationAction) async { var uri = navigationAction.request.url!; if (![ "http", "https", "file", "chrome", "data", "javascript", "about"].contains(uri.scheme)) { String targetUrl = uri.toString(); if (await canLaunch(targetUrl)) { await launch(targetUrl); return NavigationActionPolicy.CANCEL; } } return NavigationActionPolicy.ALLOW; }, - 增加应用生命周期监听,切回前台时主动恢复WebView状态
- 首先给
_MyAppState类混入生命周期监听能力:将类定义从class _MyAppState extends State<MyApp>改为class _MyAppState extends State<MyApp> with WidgetsBindingObserver - 在
initState方法中注册生命周期监听,在dispose方法中释放监听:
@override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); // 原有pullToRefreshController初始化逻辑保留 pullToRefreshController = PullToRefreshController( options: PullToRefreshOptions( color: Colors.blue, ), onRefresh: () async { if (Platform.isAndroid) { webViewController?.reload(); } else if (Platform.isIOS) { webViewController?.loadUrl( urlRequest: URLRequest(url: await webViewController?.getUrl())); } }, ); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); }- 在State中新增生命周期回调方法,应用切回前台时主动触发WebView渲染层重建:
@override void didChangeAppLifecycleState(AppLifecycleState state) async { // 仅处理Android端前台恢复场景,iOS无此问题 if (state == AppLifecycleState.resumed && Platform.isAndroid && webViewController != null) { // 等待Flutter渲染树恢复完成后再操作WebView,避免时序问题 await Future.delayed(const Duration(milliseconds: 100)); // 触发WebView渲染层重建 webViewController?.android?.resumeTimers(); webViewController?.reload(); } } - 首先给
- 可选兼容配置
如果上述方案在部分定制ROM上仍偶现卡死,可以修改AndroidManifest.xml中MainActivity的启动模式,不要使用singleInstance,改为默认的standard或singleTop即可;如果仍有问题,可以临时将Android端WebView配置中的useHybridComposition: true改为false,使用虚拟渲染模式规避Surface回收问题,注意该模式在部分机型上可能出现WebView内输入框焦点异常,优先使用生命周期恢复方案。
验证方式
- 启动应用确认网页加载、滚动、底部导航按钮点击均正常
- 切换到其他应用停留5-10秒,可打开多个内存占用较高的应用触发系统资源回收
- 切回原应用,确认网页可正常滚动、控件响应正常,无需重启即可使用
内容的提问来源于stack exchange,提问作者Sias Costantino
相关产品推荐
相关产品推荐

