Reputation: 9103
I am using google_mobile_ads: ^1.1.0
version on Flutter and following the video here:
https://www.youtube.com/watch?v=m0d_pbgeeG8
Apart some small changes respect to the video (I guess not fully up to date compare to the most recent API changes) I have now the following code:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final initFuture = MobileAds.instance.initialize();
final adState = AdState(initFuture);
await SystemChrome.setPreferredOrientations(<DeviceOrientation>[
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]).then((_) => runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Something()),
...some other ChangeNotifierProvider...,
Provider<AdState>(create: (_) => adState)
],
child: const MyApp()
),
));
}
with AdState
:
import 'dart:io';
import 'package:google_mobile_ads/google_mobile_ads.dart';
class AdState {
Future<InitializationStatus> initialisation;
AdState(this.initialisation);
String get bannerAdUnitId => Platform.isAndroid
? 'ca-app-pub-3940256099942544/6300978111'
: 'ca-app-pub-3940256099942544/2934735716'; // ios
BannerAdListener get adListener => _adListener;
final BannerAdListener _adListener = BannerAdListener(
// Called when an ad is successfully received.
onAdLoaded: (Ad ad) => print('Ad loaded: ${ad.adUnitId}.'),
onAdClosed: (Ad ad) {
ad.dispose();
print('Ad closed: ${ad.adUnitId}.');
},
// Called when an ad request failed.
onAdFailedToLoad: (Ad ad, LoadAdError error) {
ad.dispose();
print('Ad failed to load: : ${ad.adUnitId}, $error');
},
// Called when an ad opens an overlay that covers the screen.
onAdOpened: (Ad ad) => print('Ad opened: ${ad.adUnitId}.'),
// Called when an impression occurs on the ad.
onAdImpression: (Ad ad) => print('Ad impression: ${ad.adUnitId}.'),
);
}
then in the home page widget state class:
BannerAd? banner;
@override
void didChangeDependencies() {
super.didChangeDependencies();
final adState = Provider.of<AdState>(context);
adState.initialisation.then((status) {
setState(() {
banner = BannerAd(
adUnitId: adState.bannerAdUnitId,
size: AdSize.banner,
request: const AdRequest(),
listener: adState.adListener
)..load();
});
});
}
@override
Widget build(BuildContext context) {
...somewhere in the middle...
if (banner == null)
const SizedBox(height: 50)
else
SizedBox (height:50, child: AdWidget(ad: banner!)),
....
}
The error I am getting is:
AdWidget requires Ad.load to be called before AdWidget is inserted into the tree
load()
method is called in the didChangeDependencies()
method above but of course it returns a Future
so I think it may still not being there when the build()
is being run. How can I fix that?
Upvotes: 2
Views: 4865
Reputation: 883
Faced the same problem, this was my fix, although the try block has a lot of codes, you can fix this to your liking.
BannerAd? bottomBannerAd;
bool isBannerAdReady = false;
@override
void initState() {
createBottomBannerAd();
super.initState();
}
@override
void dispose() {
bottomBannerAd!.dispose();
isBannerAdReady = false;
super.dispose();
}
createBottomBannerAd() {
try {
bottomBannerAd = BannerAd(
adUnitId: AdHelper.bannerAdUnitId,
size: AdSize.banner,
request: const AdRequest(),
listener: BannerAdListener(
onAdLoaded: (_) {
setState(() {
isBannerAdReady = true;
});
},
onAdFailedToLoad: (ad, error) {
ad.dispose();
},
),
);
bottomBannerAd!.load();
}
catch (e){
bottomBannerAd = null;
}
}
bottomNavigationBar: isBannerAdReady && bottomBannerAd != null
? SizedBox(
height: bottomBannerAd!.size.height.toDouble(),
width: bottomBannerAd!.size.width.toDouble(),
child: AdWidget(
ad: bottomBannerAd!,
),
)
: null,
Upvotes: 0
Reputation: 29814
You can use the AdWidget
only after BannerAd
is loaded not aftar BannerAd
is not null.
So, try using a flag
for loaded state like in the following snippet:
BannerAd? banner;
bool _bannerIsLoaded = false;
@override
void didChangeDependencies() {
super.didChangeDependencies();
final adState = Provider.of<AdState>(context);
adState.initialisation.then((status) {
setState(() {
banner = BannerAd(
adUnitId: adState.bannerAdUnitId,
size: AdSize.banner,
request: const AdRequest(),
listener: adState.adListener
)..load();
_bannerIsLoaded = true;
});
});
}
@override
Widget build(BuildContext context) {
...somewhere in the middle...
if (banner != null && _bannerIsLoaded)
SizedBox (height:50, child: AdWidget(ad: banner!)),
else
const SizedBox(height: 50)
....
}
Upvotes: 5