🚨
【Flutter】Admobのバナーを複数箇所に出そうとした際に発生したエラーの解決策
現象
ListView内に一定間隔ごとにバナー広告を1つずつ設置しようとした際に以下のエラーが発生しました。
This AdWidget is already in the Widget tree
環境
- Flutterバージョン: 3.3.8
- google_mobile_ads: 2.2.0
原因
エラーの通りではありますが、同一のAdWidgetが生成されている事が原因でした。
AdWidgetの引数にBannerAd
クラスのインスタンスを渡すようになっていますが、この引数に指定したインスタンスが同一の場合に、同一のAdWidgetとして認識されるようです。
- エラーコード
Widget build(BuildContext context, WidgetRef ref) {
final myBanner = ref.watch(admobBannerProvider);
...省略
SizedBox(
height: 50.0,
child: AdWidget(ad: myBanner), // myBannerの部分が同一のインスタンスのためエラーになっていた
),
...
}
- provider定義
final admobBannerProvider = Provider<BannerAd>((ref) {
return BannerAd(
adUnitId: <広告ユニットID>,
size: AdSize.banner,
request: const AdRequest(),
listener: const BannerAdListener()
)..load();
});
余談ですが、google_mobile_ads
の旧バージョンでは同一のAdWidgetを複数箇所で使用できたみたいです。ただ、自分が使用したv2.2.0ではそのような仕様変更が入ったようでした。
解決策
バナー設置箇所(AdWidget)ごとに新しいBannerAd
クラスのインスタンスを生成してあげる。
-
BannerAd
クラスのインスタンスを生成しやすいように汎用クラスを作成。
class AdmobManager {
BannerAd get bannerAd {
return BannerAd(
adUnitId: <広告ユニットID>, // 環境ごとに取得する
size: AdSize.banner,
request: const AdRequest(),
listener: const BannerAdListener(),
)..load();
}
}
- View側でAdWidget使用箇所ごとに都度、別のインスタンスを生成して渡す。
Widget build(BuildContext context, WidgetRef ref) {
...省略
SizedBox(
height: 50.0,
child: AdWidget(ad: AdmobManager().bannerAd), // AdmobManager().bannerAd:新しいインスタンスを生成
),
...
}
無事、広告を表示することが出来ました。
最後に
2022/12/22追記
Discussion