Flutter :- 该 AdWidget 已经在 Widget 树中。如何禁用此异常。这意味着什么?

Har*_*tel 9 admob flutter flutter-dependencies firebase-admob

所以我在列表中插入了 admob 广告。我在列表视图中添加了无限滚动的功能。因此,当用户滚动到列表末尾时,新项目将添加到列表中。对于这个项目,我还在其中添加了 admob 广告。

因此,当用户滚动到末尾时,新项目和广告将添加到列表中。此时会捕获以下异常。那么如何解决这个异常呢。

======== Exception caught by widgets library =======================================================
The following assertion was thrown building AdWidget-[#53ef3](dirty, state: _AdWidgetState#850ac):
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.

The relevant error-causing widget was: 
  AdWidget-[#53ef3] file:///D:/flutter%20project/memer/lib/pages/TimeLinePage.dart:198:42
When the exception was thrown, this was the stack: 
#0      _AdWidgetState.build (package:google_mobile_ads/src/ad_containers.dart:371:7)
#1      StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
#2      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4495:15)
#3      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4667:11)
#4      Element.rebuild (package:flutter/src/widgets/framework.dart:4189:5)
Run Code Online (Sandbox Code Playgroud)

代码:-

return ListView.builder(itemBuilder: (context, index){
        //print(posts);
        if(posts[index] is Post){
          return posts[index];
        }
        else{
          final Container adContainer = Container(
                                  alignment: Alignment.center,
                                  child: AdWidget(key: UniqueKey(), ad: posts[index] as BannerAd),//AdmobService.createBannerAd()..load()
                                  height: 50,
                              );
                      return adContainer;
        }
      },itemCount: posts.length,
          controller: scrollController,physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()));
    }
Run Code Online (Sandbox Code Playgroud)

iqf*_*eez 13

除了 Kafil Khan 的答案之外,您还可以使用 来包装 Container 小部件StatefulBuilder

例子:

Widget bannerAdWidget() {
    return StatefulBuilder(
      builder: (context, setState) => Container(
        child: AdWidget(ad: _bannerAd),
        width: _bannerAd.size.width.toDouble(),
        height: 100.0,
        alignment: Alignment.center,
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)

  • 看来可以工作了。将持续关注。解释一下为什么这样做会很有帮助。 (2认同)

小智 8

问题是您一次又一次地放置相同的小部件。您可以通过创建一个新StatefulWidget类并返回 Adwidget 来解决此问题,这将多次构建相同的小部件,它的工作方式类似于构建器。这解决了我的问题,希望它也对你有用!:)

您也不必为单个广告单元提供多个 ID。

  • 即使使用 StatefulWidget 我仍然遇到同样的错误 (2认同)

小智 8

#Step-1:创建一个有状态的类,如下所示:

import 'package:flutter/cupertino.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

class BannerAdmob extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return _BannerAdmobState();
  }
}

class _BannerAdmobState extends State<BannerAdmob>{

  late BannerAd _bannerAd;
  bool _bannerReady = false;

  @override
  void initState() {
    super.initState();
    _bannerAd = BannerAd(
      adUnitId: "ca-app-pub-3940256099942544/6300978111",
      request: const AdRequest(),
      size: AdSize.largeBanner,
      listener: BannerAdListener(
        onAdLoaded: (_) {
          setState(() {
            _bannerReady = true;
          });
        },
        onAdFailedToLoad: (ad, err) {
          setState(() {
            _bannerReady = false;
          });
          ad.dispose();
        },
      ),
    );
    _bannerAd.load();
  }

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

  @override
  Widget build(BuildContext context) {
    return _bannerReady?SizedBox(
      width: _bannerAd.size.width.toDouble(),
      height: _bannerAd.size.height.toDouble(),
      child: AdWidget(ad: _bannerAd),
    ):Container();
  }
}
Run Code Online (Sandbox Code Playgroud)

#Step-2:使用如下:

@override
Widget build(BuildContext context){
  return BannerAdmob();
}
Run Code Online (Sandbox Code Playgroud)