Flutter中BannerAd/WebView从后台恢复后显示空白问题求助
应用从后台恢复后,BannerAd显示黑色空白页面。已知google_mobile_ads在Flutter中基于webview_flutter包实现,WebView也存在相同的后台恢复空白问题。AdMob/WebView的点击、滚动等功能均正常,仅渲染空白,即使新建仅包含广告的工程也会复现该问题。
以下是仅包含简单BannerAd的代码,在Flutter 3.16.3、Pixel 7 Pro设备上会出现后台恢复后空白的情况:
import 'package:flutter/material.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; void main(){ runApp(MaterialApp(home:AD())); } class AD extends StatefulWidget{ @override State createState()=>_AD(); } class _AD extends State<AD>{ BannerAd?_ADBANNER; final ValueNotifier<bool>_READY=ValueNotifier<bool>(false); @override void initState(){ super.initState(); MobileAds.instance.initialize(); if(null==_ADBANNER) _ADBANNER= BannerAd( adUnitId:'ca-app-pub-3940256099942544/6300978111', size:AdSize.banner, request:AdRequest(), listener:BannerAdListener( onAdLoaded:(AD){ debugPrint('Ad loaded'); if(!_READY.value) _READY.value=true; }, onAdFailedToLoad:(AD,E){ debugPrint('Ad failed to load: $E'); _READY.value=false; AD.dispose(); }, ), ) ..load(); } @override void dispose(){ _READY.value=false; _ADBANNER?.dispose(); debugPrint('Ad disposed'); super.dispose(); } @override Widget build(CTX){ return ValueListenableBuilder<bool>( valueListenable:_READY, builder:(CTX,V,_){ debugPrint('LISTEN'); if(V) return Container( alignment:Alignment.center, color:Colors.white, child: AdWidget(ad:_ADBANNER!), ); else return Center(child:CircularProgressIndicator()); } ); } }
补充信息:
- 该问题仅在Pixel 7 Pro和Mi A1真机上出现,模拟器无此问题,调试控制台无错误。
- 同时使用BannerAd和WebView时,SliverGrid进入视口后BannerAd会出现显示错乱,重复WebView画面。
请问我的代码中遗漏了什么?
解决方案
这个问题本质是Android平台上WebView(及基于它的google_mobile_ads)在后台恢复时的渲染层异常,和你的代码逻辑本身无关,可通过以下方式修复:
监听App生命周期,前台恢复时重新加载广告
在State类中添加App生命周期监听,当应用从后台回到前台时,销毁旧广告并重新加载,强制重建渲染层:@override void initState() { super.initState(); MobileAds.instance.initialize(); _loadBannerAd(); // 注册生命周期监听 WidgetsBinding.instance.addObserver(this); } @override void dispose() { // 移除监听 WidgetsBinding.instance.removeObserver(this); _disposeBannerAd(); super.dispose(); } // 重写生命周期回调 @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (state == AppLifecycleState.resumed) { // 回到前台时重置广告 _disposeBannerAd(); _loadBannerAd(); } } // 封装广告加载方法 void _loadBannerAd() { _ADBANNER = BannerAd( adUnitId: 'ca-app-pub-3940256099942544/6300978111', size: AdSize.banner, request: AdRequest(), listener: BannerAdListener( onAdLoaded: (AD) { debugPrint('Ad loaded'); _READY.value = true; }, onAdFailedToLoad: (AD, E) { debugPrint('Ad failed to load: $E'); _READY.value = false; AD.dispose(); }, ), )..load(); } // 封装广告销毁方法 void _disposeBannerAd() { _READY.value = false; _ADBANNER?.dispose(); _ADBANNER = null; debugPrint('Ad disposed'); }解决BannerAd与WebView共存的显示错乱
两者同屏时Android硬件加速层易冲突,可通过隔离渲染层解决:
给AdWidget所在容器添加RepaintBoundary包裹,避免渲染层串扰:Container( alignment: Alignment.center, color: Colors.white, child: RepaintBoundary( child: AdWidget(ad: _ADBANNER!), ), )更新依赖版本
确保google_mobile_ads和webview_flutter使用最新稳定版,旧版本存在此类渲染bug的概率更高。
内容的提问来源于stack exchange,提问作者facebook-570128180
相关产品推荐
相关产品推荐

