Git Product home page Git Product logo

Comments (10)

bdlukaa avatar bdlukaa commented on August 17, 2024 1

Well, something is wrong on your code. The best code demonstration I can show you is the example app, which the ad preloading (the first ad) is working just fine for me. Even when I swipe to refresh (https://github.com/bdlukaa/native_admob_flutter/blob/master/example/lib/screens/native_ads.dart#L30), the first ad, which has the controller, is kept the same, when the other ads get changed.

I have just done some experiments on my machine with prints and everything, and it gets printed only once, even when the NativeAd is removed from the tree and added back. That proves the controller IS keeping the ad.

we'll get the error mentioned in my previous reply

In my tests, the only possible way to get this error is when the controller is provided to multiple native ads. You gotta make sure the ad is being provided only once.

In the link below in your Wiki you've mentioned a similar case:
https://github.com/bdlukaa/native_admob_flutter/wiki/Native-Ad-builder-and-placeholders#do
Does the case still remain for the latest versions?

Yes

from native_admob_flutter.

bdlukaa avatar bdlukaa commented on August 17, 2024

Hey! Ads shouldn't be reloading on setState. Can you show your code? In the example app I consistently call setState to switch between pages. Can you take a look at it? example

from native_admob_flutter.

bdlukaa avatar bdlukaa commented on August 17, 2024

Closing as duplicate of #36

from native_admob_flutter.

ramtinq avatar ramtinq commented on August 17, 2024

You're right, but I'm not sure what's causing the ads to reload. I'm using your plugin with the tcard package, and after each swipe, all ads are being reloaded. This is my code and would really appreciate any suggestions about what is causing this effect:

main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:native_admob_flutter/native_admob_flutter.dart';

import 'screens/native_ads.dart';
import 'package:tcard/tcard.dart';

void main() async {
  /// Make sure you add this line here, so the plugin can access the native side
  WidgetsFlutterBinding.ensureInitialized();

  /// Make sure to initialize the MobileAds sdk. It returns a future
  /// that will be completed as soon as it initializes
  await MobileAds.initialize();
  // This is my device id. Ad yours here
  MobileAds.setTestDeviceIds(['7fccbe9154849d0472a2d0677a3daeaf']);

  /// Run the app
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    // appOpenAd.show();
    return MaterialApp(
      title: 'Native Ads Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  /// Init the controller
  final bannerController = BannerAdController();

  /// The banner height
  // double _bannerAdHeight = 0;

  @override
  void initState() {
    super.initState();

    bannerController.onEvent.listen((e) {
      final event = e.keys.first;
      // final info = e.values.first;
      switch (event) {
        case BannerAdEvent.loaded:
        // setState(() => _bannerAdHeight = (info as int)?.toDouble());
          break;
        default:
          break;
      }
    });
    bannerController.load();


  }

  @override
  void dispose() {
    //bannerController.dispose();
    super.dispose();
  }

  TCardController _controller = TCardController();

  int _index = 0;

  List<Color> colors = [
    Colors.blue,
    Colors.yellow,
    Colors.red,
    Colors.orange,
    Colors.pink,
    Colors.amber,
    Colors.cyan,
    Colors.purple,
    Colors.brown,
    Colors.teal,
  ];

  List<Widget> cards = [
    Container(
        color: Colors.blue,
        child: Image(image: NetworkImage("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"))
    ),
    Container(
      color: Colors.yellow,
      child: NativeAds(),
      //child: Text("hooooy"),

    ),
    Container(
        color: Colors.blue,
        child: Image(image: NetworkImage("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"))
    ),
    Container(
      color: Colors.yellowAccent,
      child: NativeAds(),
      //child: Text("hey"),

    ),
    Container(
        color: Colors.blue,
        child: Image(image: NetworkImage("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"))
    ),
  ];

  void setTheState() {
    setState(() {
      cards.insert(0, Container(
          color: Colors.blue,
          child: Image(image: NetworkImage("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"))
      ));
      _controller.reset();

    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child:TCard(
                cards: cards,
                controller: _controller,
                onForward: (index, info) {
                  _index = index;
                  print(info.direction);
                  setState(() {});
                },
                onBack: (index, info) {
                  _index = index;
                  setState(() {});
                },
                onEnd: () {
                  print('end');
                }

            )), floatingActionButton: MaterialButton(
      color: Colors.red,
        onPressed: setTheState )
    );
  }
}

native_ads.dart

import 'package:flutter/material.dart';
import 'package:native_admob_flutter/native_admob_flutter.dart';

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

  @override
  _NativeAdsState createState() => _NativeAdsState();
}

class _NativeAdsState extends State<NativeAds>
    with AutomaticKeepAliveClientMixin {
  Widget child;

  final controller = NativeAdController();

  @override
  void initState() {
    super.initState();
    controller.load();
    controller.onEvent.listen((event) {
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
     if(controller.isLoaded)
          return NativeAd(
            height: 300,
            //unitId: MobileAds.nativeAdVideoTestUnitId,
              unitId: "ca-app-pub-3940256099942544/3986624511",
            builder: (context, child) {
              return Material(
                elevation: 8,
                child: child,
              );
            },
            buildLayout: fullBuilder,
            loading: Text('loading'),
            error: Text('error'),
            icon: AdImageView(size: 40),
            headline: AdTextView(
              style: TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.bold,
                color: Colors.white,
              ),
              maxLines: 1,
            ),
            media: AdMediaView(
              height: 180,
              width: MATCH_PARENT,
              elevation: 6,
              elevationColor: Colors.deepPurpleAccent,
            ),
            attribution: AdTextView(
              width: WRAP_CONTENT,
              height: WRAP_CONTENT,
              padding: EdgeInsets.symmetric(horizontal: 2, vertical: 0),
              margin: EdgeInsets.only(right: 4),
              maxLines: 1,
              text: 'Anúncio',
              decoration: AdDecoration(
                borderRadius: AdBorderRadius.all(10),
                border: BorderSide(color: Colors.green, width: 1),
              ),
              style: TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
              ),
            ),
            button: AdButtonView(
              elevation: 18,
              elevationColor: Colors.amber,
              height: MATCH_PARENT,
            )
    );
     else{
               return Text("loaaaaaading");
     }



  }

  @override
  bool get wantKeepAlive => true;
}

AdLayoutBuilder get fullBuilder => (ratingBar, media, icon, headline,
    advertiser, body, price, store, attribuition, button) {
  return AdLinearLayout(
    padding: EdgeInsets.all(10),
    // The first linear layout width needs to be extended to the
    // parents height, otherwise the children won't fit good
    width: MATCH_PARENT,
    decoration: AdDecoration(
        gradient: AdLinearGradient(
          colors: [Colors.indigo[300], Colors.indigo[700]],
          orientation: AdGradientOrientation.tl_br,
        )),
    children: [
      media,
      AdLinearLayout(
        children: [
          icon,
          AdLinearLayout(children: [
            headline,
            AdLinearLayout(
              children: [attribuition, advertiser, ratingBar],
              orientation: HORIZONTAL,
              width: MATCH_PARENT,
            ),
          ], margin: EdgeInsets.only(left: 4)),
        ],
        gravity: LayoutGravity.center_horizontal,
        width: WRAP_CONTENT,
        orientation: HORIZONTAL,
        margin: EdgeInsets.only(top: 6),
      ),
      AdLinearLayout(
        children: [button],
        orientation: HORIZONTAL,
      ),
    ],
  );
};

AdLayoutBuilder get secondBuilder => (ratingBar, media, icon, headline,
    advertiser, body, price, store, attribution, button) {
  return AdLinearLayout(
    padding: EdgeInsets.all(10),
    // The first linear layout width needs to be extended to the
    // parents height, otherwise the children won't fit good
    width: MATCH_PARENT,
    orientation: HORIZONTAL,
    decoration: AdDecoration(
      gradient: AdRadialGradient(
        colors: [Colors.blue[300], Colors.blue[900]],
        center: Alignment(0.5, 0.5),
        radius: 1000,
      ),
    ),
    children: [
      icon,
      AdLinearLayout(
        children: [
          headline,
          AdLinearLayout(
            children: [attribution, advertiser, ratingBar],
            orientation: HORIZONTAL,
            width: WRAP_CONTENT,
            height: 20,
          ),
          button,
        ],
        margin: EdgeInsets.symmetric(horizontal: 4),
      ),
    ],
  );
};

from native_admob_flutter.

bdlukaa avatar bdlukaa commented on August 17, 2024

You should pass the controller to the NativeAd widget.

from native_admob_flutter.

ramtinq avatar ramtinq commented on August 17, 2024

Did it but didn't help. I also tried making the widget stateless, passing creating the controller _MyHomePageState, passing it to the stateless widget. Now I get this error although I'm not "creating a new ad":

The following assertion was thrown building Container(bg: MaterialColor(primary value: Color(0xffffeb3b))):
This controller has already been attached to an ad. You need one controller for each
'package:native_admob_flutter/src/utils.dart':
Failed assertion: line 159 pos 7: '!isAttached'

and if I don't pass the controller, there will be no error but again the ad reloads after swiping upper cards. This is my updated code:

main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:native_admob_flutter/native_admob_flutter.dart';

//import 'screens/native_ads.dart';
import 'native_ad.dart';
//import 'screens/full_screen_ads.dart';
//import 'screens/banner_ads.dart';
import 'package:tcard/tcard.dart';

void main() async {
  /// Make sure you add this line here, so the plugin can access the native side
  WidgetsFlutterBinding.ensureInitialized();

  /// Make sure to initialize the MobileAds sdk. It returns a future
  /// that will be completed as soon as it initializes
  await MobileAds.initialize();

  // This is my device id. Ad yours here
  MobileAds.setTestDeviceIds(['B3A4BC4C6A795C10D861A84C322F1D4C']);

  /// Run the app
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    // appOpenAd.show();
    return MaterialApp(
      title: 'Native Ads Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  /// Init the controller
  //final bannerController = BannerAdController();
  final _nativeAdController = NativeAdController();

  /// The banner height
  // double _bannerAdHeight = 0;

  List<Widget> cards;

  @override
  void initState() {
    super.initState();
    /*

    bannerController.onEvent.listen((e) {
      final event = e.keys.first;
      // final info = e.values.first;
      switch (event) {
        case BannerAdEvent.loaded:
          // setState(() => _bannerAdHeight = (info as int)?.toDouble());
          break;
        default:
          break;
      }
    });
    bannerController.load();
    */

    cards = [
      Container(
          color: Colors.blue,
          child: Image(
              image: NetworkImage(
                  "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"))),
      Container(
        color: Colors.yellow,
        child: GoodNativeAd(_nativeAdController),
        //child: Text("hooooy"),
      ),
      Container(
          color: Colors.blue,
          child: Image(
              image: NetworkImage(
                  "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"))),
    ];

    _nativeAdController.load();
    _nativeAdController.onEvent.listen((event) {
      print(event.toString());
      setState(() {});
    });
  }

  @override
  void dispose() {
    //bannerController.dispose();
    super.dispose();
  }

  TCardController _controller = TCardController();

  int _index = 0;

  void setTheState() {
    setState(() {
      _controller.reset();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child: TCard(
                cards: cards,
                controller: _controller,
                onForward: (index, info) {
                  _index = index;
                  print(info.direction);
                  setState(() {});
                },
                onBack: (index, info) {
                  _index = index;
                  setState(() {});
                },
                onEnd: () {
                  print('end');
                })),
        floatingActionButton:
            MaterialButton(color: Colors.red, onPressed: setTheState));
  }
}

native_ad.dart

import 'package:flutter/material.dart';
import 'package:native_admob_flutter/native_admob_flutter.dart';

Widget GoodNativeAd(NativeAdController controller) {
  return NativeAd(
      controller: controller,
      height: 300,
      //unitId: MobileAds.nativeAdVideoTestUnitId,
      unitId: "ca-app-pub-3940256099942544/3986624511",
      builder: (context, child) {
        return Material(
          elevation: 8,
          child: child,
        );
      },
      buildLayout: fullBuilder,
      loading: Text('loading'),
      error: Text('error'),
      icon: AdImageView(size: 40),
      headline: AdTextView(
        style: TextStyle(
          fontSize: 16,
          fontWeight: FontWeight.bold,
          color: Colors.white,
        ),
        maxLines: 1,
      ),
      media: AdMediaView(
        height: 180,
        width: MATCH_PARENT,
        elevation: 6,
        elevationColor: Colors.deepPurpleAccent,
      ),
      attribution: AdTextView(
        width: WRAP_CONTENT,
        height: WRAP_CONTENT,
        padding: EdgeInsets.symmetric(horizontal: 2, vertical: 0),
        margin: EdgeInsets.only(right: 4),
        maxLines: 1,
        text: 'Anúncio',
        decoration: AdDecoration(
          borderRadius: AdBorderRadius.all(10),
          border: BorderSide(color: Colors.green, width: 1),
        ),
        style: TextStyle(
          color: Colors.white,
          fontWeight: FontWeight.bold,
        ),
      ),
      button: AdButtonView(
        elevation: 18,
        elevationColor: Colors.amber,
        height: MATCH_PARENT,
      ));
}

AdLayoutBuilder get fullBuilder => (ratingBar, media, icon, headline,
        advertiser, body, price, store, attribuition, button) {
      return AdLinearLayout(
        padding: EdgeInsets.all(10),
        // The first linear layout width needs to be extended to the
        // parents height, otherwise the children won't fit good
        width: MATCH_PARENT,
        decoration: AdDecoration(
            gradient: AdLinearGradient(
          colors: [Colors.indigo[300], Colors.indigo[700]],
          orientation: AdGradientOrientation.tl_br,
        )),
        children: [
          media,
          AdLinearLayout(
            children: [
              icon,
              AdLinearLayout(children: [
                headline,
                AdLinearLayout(
                  children: [attribuition, advertiser, ratingBar],
                  orientation: HORIZONTAL,
                  width: MATCH_PARENT,
                ),
              ], margin: EdgeInsets.only(left: 4)),
            ],
            gravity: LayoutGravity.center_horizontal,
            width: WRAP_CONTENT,
            orientation: HORIZONTAL,
            margin: EdgeInsets.only(top: 6),
          ),
          AdLinearLayout(
            children: [button],
            orientation: HORIZONTAL,
          ),
        ],
      );
    };


PS: I don't think this is duplicate of #36 because it's happening with native ads which won't auto-refresh by default.

from native_admob_flutter.

ramtinq avatar ramtinq commented on August 17, 2024

Please! Any suggestions?!

from native_admob_flutter.

bdlukaa avatar bdlukaa commented on August 17, 2024

Now I get this error although I'm not "creating a new ad":

Make sure to use one controller for each ad.

Also, do not define the widget list before, define it on the build function, so the widgets can be updated. If you define the list outside the build function, the ads won't be updated by flutter.

from native_admob_flutter.

ramtinq avatar ramtinq commented on August 17, 2024

In the link below in your Wiki you've mentioned a similar case:
https://github.com/bdlukaa/native_admob_flutter/wiki/Native-Ad-builder-and-placeholders#do
Does the case still remain for the latest versions?
I also tried putting the parent Widgets which were for decorating the NativeAd inside its builder function as recommended. But how far should we go?! at the end the NativeAd will have a StatefulWidget parent which will rebuild its children in response to user's actions, and the NativeAd reloads.

I also even tried loading the NativeAd via its controller in its StatefulWidget parent's initState() using the controller's load() method. Again, whenever the parent rebuilds its children, the NativeAd reloads.

Even if I don't add a NativeAd to the tree, use the controller to load, and then add NativeAd to the widget while passing the controller to it, will again makes it go to loading state (showing its place holder) whenever the NativeAd widget appears, and then loads an ad (although the controller.isLoaded was true before adding the NativeAd to the tree!). This case does not happen if you make a StatelessWidget which just gets the controller passed to it and just returns the NativeAd widget with the associated controller. But the whole point is to keep showing the (same) NativeAd regardless of the parent rebuilding its children (the NativeAd being one of them). And in this scenario, using the Stateless widget to prevent it being rebuilt, we'll get the error mentioned in my previous reply:

The following assertion was thrown building Container(bg: MaterialColor(primary value: Color(0xffffeb3b))):
This controller has already been attached to an ad. You need one controller for each
'package:native_admob_flutter/src/utils.dart':
Failed assertion: line 159 pos 7: '!isAttached'

In Summary I'm asking for if there's a way to rebuild the NativeAd widget and insert it to the tree without reloading the ad (somehow by using the controller).

use cases: preloading the ad, and showing/moving it in the widget tree in different situations. Like in a ListView.Builder where the ad shows up in a different index whenever the list updates, without being reloaded.

from native_admob_flutter.

bdlukaa avatar bdlukaa commented on August 17, 2024

With the above being said, this can be closed.

from native_admob_flutter.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.