Flutter使用google_mobile_ads报AdWidget已在Widget树中错误如何解决?
报错信息:
This AdWidget is already in the Widget tree
If you placed this AdWidget in a list, make sure you create a new instance in the builder function with a unique ad object.
Make sure you are not using the same ad object in more than one AdWidget.
问题根源
报错和你设置的UniqueKey无关,核心问题出在两处:
- 你提前在
StatefulBuilder的builder方法外部实例化了包含AdWidget的adContainer,每次组件触发重build时,返回的都是同一个AdWidget实例,导致同一个Widget被重复挂载到组件树。 - 若
myPollsData数组中存在同一个BannerAd实例被放在多个下标的情况,也会触发该报错,单个广告实例仅能绑定一个AdWidget。
排查步骤
- 确认
myPollsData中每个下标对应的BannerAd都是单独初始化的独立实例,没有同一个广告对象被复用在多个位置的情况 - 检查组件销毁逻辑,确认
BannerAd实例随组件销毁时同步调用了dispose()方法,避免内存残留的广告实例被重复挂载 - 排查组件树结构,确认同一个
AdWidget实例不会被同时插入到多个节点位置
修复方案
将adContainer的实例化逻辑挪到StatefulBuilder的builder方法内部,每次build都生成全新的AdWidget实例,修改后代码如下:
return StatefulBuilder( builder: (context, setS){ // 容器实例化移到builder内部,每次重build生成新实例 final adContainer = Container( alignment: Alignment.center, width: double.infinity, height: 70, child: Card( color: white, child: Container( padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 0.0), child: AdWidget( key: UniqueKey(), ad: myPollsData[index] as BannerAd, ), ), ), ); return adContainer; }, );
如果是在ListView/GridView等可滚动列表中使用,额外适配两点:
- 每个
BannerAd和对应列表项绑定,仅在列表项首次build时初始化广告,不要提前批量初始化所有广告实例 - 列表项滑出可视区被销毁时,同步调用对应
BannerAd的dispose()方法释放资源
内容的提问来源于stack exchange,提问作者GAGAN SINGH
相关产品推荐
相关产品推荐

