@@ -12,25 +12,80 @@ import 'package:logging/logging.dart';
1212/// It expects the `adObject` within the [app_ad_models.NativeAd] to be a fully
1313/// loaded [admob.NativeAd] instance.
1414/// {@endtemplate}
15- class AdmobNativeAdWidget extends StatelessWidget {
15+ /// {@template admob_native_ad_widget}
16+ /// A widget that specifically renders a Google AdMob native ad.
17+ ///
18+ /// This widget is responsible for taking the generic [app_ad_models.NativeAd]
19+ /// and rendering it using the `AdWidget` from the `google_mobile_ads` package.
20+ /// It expects the `adObject` within the [app_ad_models.NativeAd] to be a fully
21+ /// loaded [admob.NativeAd] instance.
22+ ///
23+ /// This is a [StatefulWidget] to properly manage the lifecycle of the native
24+ /// ad object, ensuring it is disposed when the widget is removed from the tree
25+ /// or when the underlying ad object changes.
26+ /// {@endtemplate}
27+ class AdmobNativeAdWidget extends StatefulWidget {
1628 /// {@macro admob_native_ad_widget}
1729 const AdmobNativeAdWidget ({required this .nativeAd, super .key});
1830
1931 /// The generic native ad model which contains the provider-specific ad object.
2032 final app_ad_models.NativeAd nativeAd;
2133
2234 @override
23- Widget build ( BuildContext context) {
24- final adObject = nativeAd.adObject;
35+ State < AdmobNativeAdWidget > createState () => _AdmobNativeAdWidgetState ();
36+ }
2537
26- // Safely cast the generic ad object to the expected AdMob native ad type.
27- if (adObject is ! admob.NativeAd ) {
28- Logger ('AdmobNativeAdWidget' ).severe (
38+ class _AdmobNativeAdWidgetState extends State <AdmobNativeAdWidget > {
39+ admob.NativeAd ? _ad;
40+ final Logger _logger = Logger ('AdmobNativeAdWidget' );
41+
42+ @override
43+ void initState () {
44+ super .initState ();
45+ _setAd ();
46+ }
47+
48+ @override
49+ void didUpdateWidget (covariant AdmobNativeAdWidget oldWidget) {
50+ super .didUpdateWidget (oldWidget);
51+ // If the nativeAd object itself has changed (e.g., a new ad was loaded
52+ // for the same placeholder ID), dispose the old ad and set the new one.
53+ if (widget.nativeAd.id != oldWidget.nativeAd.id) {
54+ _ad? .dispose ();
55+ _setAd ();
56+ }
57+ }
58+
59+ @override
60+ void dispose () {
61+ // Dispose the native ad when the widget is removed from the tree.
62+ // This is crucial for releasing native resources and preventing crashes.
63+ _ad? .dispose ();
64+ _logger.info ('AdmobNativeAdWidget disposed and native ad released.' );
65+ super .dispose ();
66+ }
67+
68+ /// Sets the internal [_ad] object from the widget's [nativeAd] .
69+ ///
70+ /// This method ensures that the adObject is of the correct type and
71+ /// logs an error if it's not.
72+ void _setAd () {
73+ if (widget.nativeAd.adObject is admob.NativeAd ) {
74+ _ad = widget.nativeAd.adObject as admob.NativeAd ;
75+ } else {
76+ _ad = null ; // Ensure _ad is null if the type is incorrect
77+ _logger.severe (
2978 'The provided ad object is not of type admob.NativeAd. '
30- 'Received: ${adObject .runtimeType }. Ad will not be displayed.' ,
79+ 'Received: ${widget . nativeAd . adObject .runtimeType }. Ad will not be displayed.' ,
3180 );
81+ }
82+ }
83+
84+ @override
85+ Widget build (BuildContext context) {
86+ if (_ad == null ) {
3287 // Return an empty widget if the ad object is not of the correct type
33- // to prevent runtime errors .
88+ // or if it was explicitly set to null due to an error .
3489 return const SizedBox .shrink ();
3590 }
3691
@@ -39,14 +94,14 @@ class AdmobNativeAdWidget extends StatelessWidget {
3994 // We wrap it in a SizedBox to provide explicit height constraints,
4095 // which is crucial for platform views (like native ads) within scrollable
4196 // lists to prevent "unbounded height" errors.
42- final adHeight = switch (nativeAd.templateType) {
43- app_ad_models.NativeAdTemplateType .small => 120 , // Example height for small template
44- app_ad_models.NativeAdTemplateType .medium => 340 , // Example height for medium template
97+ final adHeight = switch (widget. nativeAd.templateType) {
98+ app_ad_models.NativeAdTemplateType .small => 120 ,
99+ app_ad_models.NativeAdTemplateType .medium => 340 ,
45100 };
46101
47102 return SizedBox (
48103 height: adHeight.toDouble (),
49- child: admob.AdWidget (ad: adObject ),
104+ child: admob.AdWidget (ad: _ad ! ),
50105 );
51106 }
52107}
0 commit comments