Comments (10)
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.
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.
Closing as duplicate of #36
from native_admob_flutter.
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.
You should pass the controller
to the NativeAd
widget.
from native_admob_flutter.
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.
Please! Any suggestions?!
from native_admob_flutter.
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.
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.
With the above being said, this can be closed.
from native_admob_flutter.
Related Issues (20)
- Native Ad not working - MissingPluginException HOT 35
- MobileAds.initialize issue HOT 3
- The ads I implemented do not show up in AppReview. HOT 2
- Fatal Exception: java.lang.StackOverflowError (Android 9)
- Doesn't work on android 12
- Error MissingPluginException on Android 11 HOT 1
- Banner ads issue HOT 5
- Blinking in Flutter 2.8 HOT 6
- Cancel/reset rewardAd events listener HOT 1
- [iOS] Cannot find an ad network adapter with the name(s): com.google.DummyAdapter.
- Using Interstitial ad with AppOpen ad HOT 2
- [Feature Request] Mute ads at app level HOT 2
- Native Ads are not working anymore
- [QUESTION] Is it necessary to show the openAppAd from the splash screen? HOT 2
- Adaptive banner not getting size properly HOT 2
- Issue: Violation of Families Policy Requirements HOT 3
- Cannot find 'kGADAdSizeBanner' in scope HOT 17
- Not Working on Android 12
- Initializing failed
- Cannot find 'kGADAdSizeBanner' in scope
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from native_admob_flutter.