googleads / googleads-mobile-flutter

A Flutter plugin for the Google Mobile Ads SDK
Apache License 2.0
341 stars 285 forks source link

Do I need stateful widgets? #365

Closed fbuireu closed 3 years ago

fbuireu commented 3 years ago

According to the examples page all the used views are Stateful. However, I'd like to use Stateless widgets (if possible). I am creating a service to load and show ads (interstitial in this case). My goal is to call them during the user's navigation.

I have something like:

 void loadInterstitialAd() async {
    InterstitialAd.load(
      adUnitId: InterstitialAd.testAdUnitId,
      request: const AdRequest(),
      adLoadCallback: InterstitialAdLoadCallback(
        onAdLoaded: (InterstitialAd ad) {
          debugPrint('InterstitialAd loaded. Ad: $ad');
          _interstitialAd = ad;
          _interstitialAd!.setImmersiveMode(true);
        },
        onAdFailedToLoad: (LoadAdError error) {
          debugPrint('InterstitialAd failed to load: $error.');
          _loadAttempts++;
          _interstitialAd = null;
          if (_loadAttempts <= _maxFailedLoadAttempts) {
            loadInterstitialAd();
          }
        },
      ),
    );
  }

  void showInterstitialAd() async {
    if (_interstitialAd == null) {
      debugPrint('ad is null');
      loadInterstitialAd();
      return;
    }

    _interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
      onAdShowedFullScreenContent: (InterstitialAd ad) => print('ad onAdShowedFullScreenContent.'),
      onAdDismissedFullScreenContent: (InterstitialAd ad) {
        debugPrint('ad onAdShowedFullScreenContent.');

        ad.dispose();
        loadInterstitialAd();
      },
      onAdFailedToShowFullScreenContent: (InterstitialAd ad, AdError error) {
        debugPrint('$ad onAdFailedToShowFullScreenContent: $error');
        ad.dispose();
        loadInterstitialAd();
      },
      onAdImpression: (InterstitialAd ad) => debugPrint('$ad impression occurred.'),
    );
    _interstitialAd!.show();
    _interstitialAd = null;
  }

The ad is loaded (loadInterstitialAd) properly (logs are shown, etc). However, when I try to show them (showInterstitialAd) it always validates the condition _interstitialAd == null. Even if at this point I call loadInterstitialAd the ad results to null.

If I call showInterstitialAd in the onAdLoaded callback, then, the ad is prompted although I lose a little bit of control in this scenario, so I'd like to keep both functions separated.

I'm wondering if I have some scope/injection issues or it's something internal like needing stateful widgets because, as the docs point, it's statically placed:

An InterstitialAd is displayed as an Overlay on top of all app content and is statically placed. Which means it can not be added to the Flutter widget tree . You can choose when to show the ad by calling show().

fbuireu commented 3 years ago

Found another workaround: create 1 stateful widget that loads the add. This gives me control over Flutter's widget tree and over navigation observer.

uditrugman commented 3 years ago

having the user wait while your ad is loaded is not a good practice.
I'd suggest to create a preloaded pool. a limited set of interstitials ready to be shown.
whenever you show one of them, that should trigger a load of another ad for next time.
that way, all the retries occur in the background without the user waiting