除非我在 initState() 函数中放置断点,否则不会显示 Admob 横幅

Admob banner not showing unless I put a breakpoint in the initState() function

我尝试按照 AdMob 教程进行操作

https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter#6

但我似乎无法让广告横幅正常工作。

使用当前设置的代码,横幅根本不会显示。 但是,如果我在“_bannerAd.load();”行设置断点,广告就会加载并显示横幅。

我不明白为什么,所以任何帮助将不胜感激。

谢谢。

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:myapp/ad_helper_test.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'MyApp',
        theme: ThemeData(
            primarySwatch: Colors.blue,
        ),
        home: const MyAppHomePage(title: 'MyApp'),
    );
  }
}

class MyAppHomePage extends StatefulWidget {
  const MyAppHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyAppHomePage> createState() => _MyAppHomePageState();
}

class _MyAppHomePageState extends State<MyAppHomePage> {
    late BannerAd _bannerAd;
    bool _isBannerAdReady = false;

    @override
    void initState() {
        super.initState();
        _bannerAd = BannerAd(
            adUnitId: AdHelper.bannerAdUnitId,
            request: const AdRequest(),
            size: AdSize.banner,
            listener: BannerAdListener(
                onAdLoaded: (_) {
                    setState(() {
                        _isBannerAdReady = true;
                    });
                },
                onAdFailedToLoad: (ad, err) {
                    print('Failed to load a banner ad: ${err.message}');
                    _isBannerAdReady = false;
                    ad.dispose();
                },
            ),
        );

        _bannerAd.load();
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
              buildAdWidget()
          ],
        ),
      ),
    );
  }

    FutureBuilder<void> buildAdWidget() {
      return FutureBuilder<void>(
          future: _initGoogleMobileAds(),
          builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
              return Center(
                  child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                          if (_isBannerAdReady)
                              Align(
                                  alignment: Alignment.topCenter,
                                  child: SizedBox(
                                      width: _bannerAd.size.width.toDouble(),
                                      height: _bannerAd.size.height.toDouble(),
                                      child: AdWidget(ad: _bannerAd),
                                  ),
                              ),
                              
                          const Text("Here goes the rest of the app"),
                      ],
                  ),
              );
          },
      );
    }



    Future<InitializationStatus> _initGoogleMobileAds() {
        return MobileAds.instance.initialize();
    }

    @override
    void dispose() {
      super.dispose();
      _bannerAd.dispose();
    }
}

根据文档,您需要在加载横幅之前初始化框架 MobileAds.instance.initialize();。你在做相反的事情。考虑用 FutureBuilder 包装您的主页,初始化框架并在初始化时呈现您的主页,否则 returns 一些加载页面。

在教程中,他们使用路由来处理这个问题。这可能是一个公平的方式。

编辑

这没有经过测试,但它应该看起来像这样:

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:myapp/ad_helper_test.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MyApp',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const DependencyLoader(),
    );
  }
}

class DependencyLoader extends StatelessWidget {
  const DependencyLoader({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: MobileAds.instance.initialize(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          MyAppHomePage(
            title: 'MyApp',
          );
        } else {
          /// Create a loading page of some sort
        }
      },
    );
  }
}

class MyAppHomePage extends StatefulWidget {
  const MyAppHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyAppHomePage> createState() => _MyAppHomePageState();
}

class _MyAppHomePageState extends State<MyAppHomePage> {
  late BannerAd _bannerAd;
  bool _isBannerAdReady = false;

  @override
  void initState() {
    super.initState();
    _bannerAd = BannerAd(
      adUnitId: AdHelper.bannerAdUnitId,
      request: const AdRequest(),
      size: AdSize.banner,
      listener: BannerAdListener(
        onAdLoaded: (_) {
          setState(() {
            _isBannerAdReady = true;
          });
        },
        onAdFailedToLoad: (ad, err) {
          print('Failed to load a banner ad: ${err.message}');
          _isBannerAdReady = false;
          ad.dispose();
        },
      ),
    );

    _bannerAd.load();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[buildAdWidget()],
        ),
      ),
    );
  }

  Widget buildAdWidget() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          if (_isBannerAdReady)
            Align(
              alignment: Alignment.topCenter,
              child: SizedBox(
                width: _bannerAd.size.width.toDouble(),
                height: _bannerAd.size.height.toDouble(),
                child: AdWidget(ad: _bannerAd),
              ),
            ),
          const Text("Here goes the rest of the app"),
        ],
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _bannerAd.dispose();
  }
}