Flutter :- This AdWidget is already in the Widget tree. How to disable this exception. Using Provider

28 Views Asked by At

This is my Ad provider

import 'package:bg_remover/services/ads_helper.dart';
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';


class AdaptiveBannerAdProvider with ChangeNotifier {
  BannerAd? _anchoredAdaptiveAd;
  bool _isLoaded = false;

  BannerAd? get anchoredAdaptiveAd => _anchoredAdaptiveAd;

  bool get isAdLoaded => _isLoaded;

  Future<void> loadAnchoredAdaptiveAd(BuildContext context) async {
    final AnchoredAdaptiveBannerAdSize? size =
        await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(
            MediaQuery.of(context).size.width.truncate());

    if (size == null) {
      debugPrint('Unable to get height of anchored banner.');
      return;
    }

    _anchoredAdaptiveAd = BannerAd(
      adUnitId: AdHelper.bannerAdUnitId,
      size: size,
      request: const AdRequest(),
      listener: BannerAdListener(
        onAdLoaded: (Ad ad) {
          debugPrint('$ad has been >>>>>loaded: ${ad.responseInfo}');
          //there was an error of @This AdWidget is already in the Widget tree@
          // so for that we apply this widgetsBinding to notify listener
          //and place the banner add in FutureBuilder and that's work

          // WidgetsBinding.instance.addPostFrameCallback((_) {
          //   _isLoaded = true;
          //   notifyListeners();
          // });

          // Ad was not showing when loaded
          _isLoaded = true;
          notifyListeners();
        },
        onAdFailedToLoad: (Ad ad, LoadAdError error) {
          debugPrint('Anchored adaptive banner failedToLoad: $error');
          ad.dispose();
        },
      ),
    );
    return _anchoredAdaptiveAd!.load();
  }

  void disposeAd() {
    _anchoredAdaptiveAd?.dispose();
  }
}

call it here to display Ad:

 import 'package:bg_remover/utils/routes/routes_name.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:provider/provider.dart';

import '../provider/ads_provider/adaptiveBanner_ad_provider.dart';
import '../utils/colors.dart';
import '../utils/images_assets_path.dart';
import '../utils/strings.dart';
import 'bottom_tabs/home_page.dart';
import 'bottom_tabs/project_page.dart';
import 'bottom_tabs/settings_page.dart';

class HomeFeedPage extends StatefulWidget {
  const HomeFeedPage({Key? key}) : super(key: key);

  @override
  State<HomeFeedPage> createState() => _HomeFeedPageState();
}

class _HomeFeedPageState extends State<HomeFeedPage> {
  int index = 1;
  final List<Widget> pages = const [
    ProjectPage(),
    HomePage(),
    SettingsPage(),
  ];

  final List<String> icons = [
    AssetImages.projectIcon,
    AssetImages.inactiveHomeIcon,
    AssetImages.settingsIcon,
  ];

  final List<String> titles = const [
    Strings.projects,
    Strings.home,
    Strings.settings,
  ];

  void _onIconPressed(int newIndex) {
    if (newIndex == 2) {
      Navigator.pushNamed(context, RoutesName.settings);
    } else {
      setState(() {
        index = newIndex;
      });
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final adaptiveAdProvider =
        Provider.of<AdaptiveBannerAdProvider>(context, listen: false);
    adaptiveAdProvider.loadAnchoredAdaptiveAd(context);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Column(
        children: [
          Expanded(child: pages[index]),
          displayAd(),
          _buildBottomBar(),
        ],
      ),
    );
  }

  Widget _buildBottomBar() {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
      color: AppColors.bottomBarColor,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: List.generate(
          icons.length,
          (int i) => GestureDetector(
            onTap: () => _onIconPressed(i),
            child: _buildIconColumn(i),
          ),
        ),
      ),
    );
  }

  Widget _buildIconColumn(int i) {
    final bool isActiveHome = index == 1 && i == 1;
    final String iconPath = isActiveHome ? AssetImages.homeIcon : icons[i];

    return Column(
      children: [
        AnimatedContainer(
          duration: const Duration(milliseconds: 300),
          width: 70,
          height: 35,
          decoration: BoxDecoration(
            color: index == i ? AppColors.activeTabColor : Colors.transparent,
            borderRadius: BorderRadius.circular(20),
          ),
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: SvgPicture.asset(
              iconPath,
              colorFilter: ColorFilter.mode(
                index == i ? AppColors.whiteColor : AppColors.activeColor,
                BlendMode.srcIn,
              ),
            ),
          ),
        ),
        const Gap(5),
        Text(
          titles[i],
          style: TextStyle(
            color: index == i ? AppColors.whiteColor : AppColors.activeColor,
            fontWeight: index == i ? FontWeight.w700 : null,
          ),
        ),
      ],
    );
  }

  Widget displayAd() {
    return Consumer<AdaptiveBannerAdProvider>(
      builder: (context, adProvider, _) {
        if (adProvider.isAdLoaded) {
          return SizedBox(
            width: adProvider.anchoredAdaptiveAd!.size.width.toDouble(),
            height: adProvider.anchoredAdaptiveAd!.size.height.toDouble(),
            child: AdWidget(ad: adProvider.anchoredAdaptiveAd!),
          );
        } else {
          return Container(
            color: AppColors.yellowColor,
            width: adProvider.anchoredAdaptiveAd?.size.width.toDouble(),
            height: adProvider.anchoredAdaptiveAd?.size.height.toDouble(),
            child: Center(
              child: Text(
                'Ad is Loading.......',
                style: TextStyle(color: AppColors.whiteColor),
              ),
            ),
          );
        }
      },
    );
  }
 verride
  void dispose() {
    Provider.of<AdaptiveBannerAdProvider>(context, listen: false).disposeAd();
    super.dispose();
  }
}

 @

working fine when I go to next having same process to display ad show error : Flutter :- This AdWidget is already in the Widget tree. How to disable this exception. And what does it mean?

Above Code is Working fine on HomeFeed Page. when I go to next having same process to display ad error : Flutter :- This AdWidget is already in the Widget tree. How to disable this exception. And what does it mean?

0

There are 0 best solutions below