Skip to content

Commit ccd0b38

Browse files
committed
Add multi inline adaptive banner example with recycling
1 parent ccb243a commit ccd0b38

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

packages/google_mobile_ads/example/lib/main.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import 'dart:developer';
2323
import 'anchored_adaptive_example.dart';
2424
import 'fluid_example.dart';
2525
import 'inline_adaptive_example.dart';
26+
import 'multi_adaptive_inline_with_recycle_example.dart';
2627
import 'native_template_example.dart';
2728
import 'reusable_inline_example.dart';
2829
import 'webview_example.dart';
@@ -55,6 +56,7 @@ class _MyAppState extends State<MyApp> {
5556
static const rewardedInterstitialButtonText = 'RewardedInterstitialAd';
5657
static const fluidButtonText = 'Fluid';
5758
static const inlineAdaptiveButtonText = 'Inline adaptive';
59+
static const mulipleInlineAdaptiveWithRecycleButtonText = 'Multiple inline adaptive with recycle';
5860
static const anchoredAdaptiveButtonText = 'Anchored adaptive';
5961
static const nativeTemplateButtonText = 'Native template';
6062
static const webviewExampleButtonText = 'Register WebView';
@@ -271,6 +273,13 @@ class _MyAppState extends State<MyApp> {
271273
builder: (context) => InlineAdaptiveExample()),
272274
);
273275
break;
276+
case mulipleInlineAdaptiveWithRecycleButtonText:
277+
Navigator.push(
278+
context,
279+
MaterialPageRoute(
280+
builder: (context) => MultiInlineAdaptiveWithRecycleExample()),
281+
);
282+
break;
274283
case anchoredAdaptiveButtonText:
275284
Navigator.push(
276285
context,
@@ -324,6 +333,10 @@ class _MyAppState extends State<MyApp> {
324333
value: inlineAdaptiveButtonText,
325334
child: Text(inlineAdaptiveButtonText),
326335
),
336+
PopupMenuItem<String>(
337+
value: mulipleInlineAdaptiveWithRecycleButtonText,
338+
child: Text(mulipleInlineAdaptiveWithRecycleButtonText),
339+
),
327340
PopupMenuItem<String>(
328341
value: anchoredAdaptiveButtonText,
329342
child: Text(anchoredAdaptiveButtonText),
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import 'dart:io';
2+
import 'package:flutter/material.dart';
3+
import 'package:collection/collection.dart';
4+
import 'package:google_mobile_ads/google_mobile_ads.dart';
5+
6+
class MultiInlineAdaptiveWithRecycleExample extends StatefulWidget {
7+
const MultiInlineAdaptiveWithRecycleExample({super.key});
8+
9+
@override
10+
State<StatefulWidget> createState() => _MultiInlineAdaptiveWithRecycleExampleState();
11+
}
12+
13+
class _MultiInlineAdaptiveWithRecycleExampleState extends State<MultiInlineAdaptiveWithRecycleExample> {
14+
15+
// A list of all the banners created.
16+
final List<BannerAd> _banners = [];
17+
// Keep track of sizes of the banners (since they can be different sizes).
18+
final Map<BannerAd, AdSize> _bannerSizes = {};
19+
20+
// The maximum number of banners we create.
21+
static const _cacheSize = 10;
22+
// Keep track of the positions of banners.
23+
final Map<BannerAd, int> _bannerPositions = {};
24+
25+
BannerAd _createBannerAd() {
26+
final String bannerId = Platform.isAndroid
27+
? 'ca-app-pub-3940256099942544/6300978111'
28+
: 'ca-app-pub-3940256099942544/2934735716';
29+
AdSize adSize = AdSize.getCurrentOrientationInlineAdaptiveBannerAdSize(360);
30+
final BannerAd bannerAd = BannerAd(
31+
adUnitId: bannerId,
32+
request: const AdRequest(),
33+
size: adSize,
34+
listener: BannerAdListener(
35+
onAdLoaded: (Ad ad) async {
36+
BannerAd bannerAd = (ad as BannerAd);
37+
final AdSize? adSize = await bannerAd.getPlatformAdSize();
38+
// When the banner size is updated, we want to rebuild.
39+
if (adSize != null && adSize != _bannerSizes[bannerAd]) {
40+
setState(() {
41+
_bannerSizes[bannerAd] = adSize;
42+
});
43+
}
44+
},
45+
),
46+
);
47+
bannerAd.load();
48+
return bannerAd;
49+
}
50+
51+
BannerAd _getRecycledBannerAd(int bannerPosition) {
52+
// If we already created a banner for this position, just reuse it.
53+
BannerAd? bannerAd = _banners.firstWhereOrNull((banner) => _bannerPositions[banner] == bannerPosition);
54+
if (bannerAd != null) {
55+
return bannerAd;
56+
}
57+
58+
// If the cache is not full, create a new banner
59+
if (_banners.length < _cacheSize) {
60+
BannerAd bannerAd = _createBannerAd();
61+
_banners.add(bannerAd);
62+
_bannerPositions[bannerAd] = bannerPosition;
63+
return bannerAd;
64+
}
65+
66+
// Now the cache is full, we should recycle the banner (if possible).
67+
BannerAd banner = _banners[bannerPosition % _cacheSize];
68+
if (banner.isMounted) {
69+
// Create a new banner if it's not possible to recycle the banner
70+
// e.g. show 15 banners on screen, but _cacheSize is only 10.
71+
return _createBannerAd();
72+
} else {
73+
// Found a recyclable banner, mark it as being used by current banner position.
74+
_bannerPositions[banner] = bannerPosition;
75+
return banner;
76+
}
77+
}
78+
79+
@override
80+
Widget build(BuildContext context) {
81+
return Scaffold(
82+
appBar: AppBar(title: Text('Adaptive Size, Recycle')),
83+
body: ListView.builder(
84+
// Arbitrary example of 1000 items in the list.
85+
itemCount: 1000,
86+
itemBuilder: (BuildContext context, int index) {
87+
// We show a banner every 3 rows (i.e. row index 0, 3, 6, 9, 12, etc will be banner row)
88+
if (index % 3 == 0) {
89+
int bannerPosition = index ~/ 3;
90+
BannerAd bannerAd = _getRecycledBannerAd(bannerPosition);
91+
final AdSize? adSize = _bannerSizes[bannerAd];
92+
if (adSize == null) {
93+
// Null adSize means the banner's content is not fetched yet.
94+
return SizedBox(height: 50, child: Text("banner is loading"));
95+
} else {
96+
// Now this banner is loaded with ad content and corresponding ad size.
97+
return SizedBox(width: adSize.width.toDouble(), height: adSize.height.toDouble(), child: AdWidget(ad: bannerAd));
98+
}
99+
} else {
100+
// Show your regular non-ad content.
101+
return SizedBox(height: 200, child: ColoredBox(color: Colors.yellow));
102+
}
103+
}),
104+
);
105+
}
106+
}

0 commit comments

Comments
 (0)