Skip to content

Commit c3d1b14

Browse files
committed
feat(ads): implement AdMob native ad widget
- Create AdMobNativeAdWidget to render Google AdMob native ads - Handle lifecycle management of native ad object - Display ad using AdMob SDK's AdWidget - Add type checking for adObject to ensure it's an AdMob NativeAd - Provide fallback for unloaded or incorrect ad types
1 parent 431e919 commit c3d1b14

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_news_app_mobile_client_full_source_code/ads/models/native_ad.dart'
3+
as app_native_ad;
4+
import 'package:google_mobile_ads/google_mobile_ads.dart' as admob;
5+
6+
/// {@template admob_native_ad_widget}
7+
/// A widget responsible for rendering a Google AdMob native ad.
8+
///
9+
/// This widget takes our generic [app_native_ad.NativeAd] model, extracts
10+
/// the underlying [admob.NativeAd] object, and uses the AdMob SDK's
11+
/// [admob.AdWidget] to display it. It also handles the lifecycle
12+
/// management of the native ad object.
13+
/// {@endtemplate}
14+
class AdMobNativeAdWidget extends StatefulWidget {
15+
/// {@macro admob_native_ad_widget}
16+
const AdMobNativeAdWidget({
17+
required this.nativeAd,
18+
super.key,
19+
});
20+
21+
/// The generic native ad data containing the AdMob-specific ad object.
22+
final app_native_ad.NativeAd nativeAd;
23+
24+
@override
25+
State<AdMobNativeAdWidget> createState() => _AdMobNativeAdWidgetState();
26+
}
27+
28+
class _AdMobNativeAdWidgetState extends State<AdMobNativeAdWidget> {
29+
admob.NativeAd? _admobNativeAd;
30+
bool _isAdLoaded = false;
31+
32+
@override
33+
void initState() {
34+
super.initState();
35+
_initializeAd();
36+
}
37+
38+
@override
39+
void didUpdateWidget(covariant AdMobNativeAdWidget oldWidget) {
40+
super.didUpdateWidget(oldWidget);
41+
// If the underlying ad object changes, dispose the old one and initialize the new one.
42+
if (widget.nativeAd.adObject != oldWidget.nativeAd.adObject) {
43+
_disposeOldAd();
44+
_initializeAd();
45+
}
46+
}
47+
48+
void _initializeAd() {
49+
// Ensure the adObject is of the expected AdMob NativeAd type.
50+
if (widget.nativeAd.adObject is admob.NativeAd) {
51+
_admobNativeAd = widget.nativeAd.adObject as admob.NativeAd;
52+
_isAdLoaded = true;
53+
} else {
54+
_admobNativeAd = null;
55+
_isAdLoaded = false;
56+
// Log an error if the adObject is not the expected type.
57+
debugPrint(
58+
'AdMobNativeAdWidget: Expected admob.NativeAd, but received '
59+
'${widget.nativeAd.adObject.runtimeType}. Ad will not be displayed.',
60+
);
61+
}
62+
}
63+
64+
void _disposeOldAd() {
65+
_admobNativeAd?.dispose();
66+
_admobNativeAd = null;
67+
_isAdLoaded = false;
68+
}
69+
70+
@override
71+
void dispose() {
72+
_disposeOldAd();
73+
super.dispose();
74+
}
75+
76+
@override
77+
Widget build(BuildContext context) {
78+
if (!_isAdLoaded || _admobNativeAd == null) {
79+
// If the ad is not loaded or is of the wrong type, return an empty container.
80+
return const SizedBox.shrink();
81+
}
82+
83+
// Use the AdMob SDK's AdWidget to render the native ad.
84+
return admob.AdWidget(ad: _admobNativeAd!);
85+
}
86+
}

0 commit comments

Comments
 (0)