Skip to content

Commit 1fba26f

Browse files
committed
feat(ads): implement native ad feed item widget
Create a new widget for displaying native ads within the feed. This widget: - Takes an AdFeedItem and renders it using AdWidget. - Handles the disposal of the NativeAd to prevent memory leaks. - Shows an empty container if the ad is not loaded. This change allows for better integration of native ads within the app's content feed.
1 parent e03b3a8 commit 1fba26f

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_news_app_mobile_client_full_source_code/ads/models/ad_feed_item.dart';
3+
import 'package:google_mobile_ads/google_mobile_ads.dart';
4+
import 'package:ui_kit/ui_kit.dart';
5+
6+
/// {@template ad_feed_item_widget}
7+
/// A widget responsible for rendering a native ad within the feed.
8+
///
9+
/// This widget takes an [AdFeedItem] and uses the `AdWidget` from the
10+
/// `google_mobile_ads` package to display the underlying [NativeAd].
11+
/// It also handles the disposal of the ad object to prevent memory leaks.
12+
/// {@endtemplate}
13+
class AdFeedItemWidget extends StatefulWidget {
14+
/// {@macro ad_feed_item_widget}
15+
const AdFeedItemWidget({required this.adFeedItem, super.key});
16+
17+
/// The ad feed item containing the loaded native ad to be displayed.
18+
final AdFeedItem adFeedItem;
19+
20+
@override
21+
State<AdFeedItemWidget> createState() => _AdFeedItemWidgetState();
22+
}
23+
24+
class _AdFeedItemWidgetState extends State<AdFeedItemWidget> {
25+
NativeAd? _nativeAd;
26+
bool _isAdLoaded = false;
27+
28+
@override
29+
void initState() {
30+
super.initState();
31+
_nativeAd = widget.adFeedItem.nativeAd;
32+
// The ad is typically already loaded by the AdService before being passed here.
33+
// We can set the state to reflect this.
34+
if (_nativeAd != null) {
35+
_isAdLoaded = true;
36+
}
37+
}
38+
39+
@override
40+
void dispose() {
41+
// Dispose the native ad when the widget is removed from the tree.
42+
_nativeAd?.dispose();
43+
super.dispose();
44+
}
45+
46+
@override
47+
Widget build(BuildContext context) {
48+
final nativeAd = _nativeAd;
49+
if (!_isAdLoaded || nativeAd == null) {
50+
// If the ad is not loaded for any reason, return an empty container.
51+
return const SizedBox.shrink();
52+
}
53+
54+
return Card(
55+
margin: const EdgeInsets.symmetric(
56+
vertical: AppSpacing.sm,
57+
horizontal: AppSpacing.lg,
58+
),
59+
child: SizedBox(
60+
height: 120,
61+
child: AdWidget(ad: nativeAd),
62+
),
63+
);
64+
}
65+
}

0 commit comments

Comments
 (0)