Skip to content

Commit 9e8510e

Browse files
committed
refactor(ads): consolidate inline ad loading logic
- Introduce private helper method _loadInlineAd to unify native and banner ad loading - Rename getInlineAd to getFeedAd for clarity in feed context - Simplify ad loading process by removing AdFeedItem wrapping - Improve logging and error handling
1 parent cbec1de commit 9e8510e

File tree

1 file changed

+65
-106
lines changed

1 file changed

+65
-106
lines changed

lib/ads/ad_service.dart

Lines changed: 65 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import 'package:core/core.dart';
22
import 'package:flutter_news_app_mobile_client_full_source_code/ads/ad_provider.dart';
3-
import 'package:flutter_news_app_mobile_client_full_source_code/ads/models/ad_feed_item.dart';
3+
import 'package:core/core.dart';
4+
import 'package:flutter_news_app_mobile_client_full_source_code/ads/ad_provider.dart';
45
import 'package:flutter_news_app_mobile_client_full_source_code/ads/models/ad_theme_style.dart';
5-
// Import BannerAd
66
import 'package:flutter_news_app_mobile_client_full_source_code/ads/models/inline_ad.dart'; // Import InlineAd
77
import 'package:flutter_news_app_mobile_client_full_source_code/ads/models/interstitial_ad.dart';
8-
// Import NativeAd
98
import 'package:logging/logging.dart';
109
import 'package:uuid/uuid.dart';
1110

@@ -44,105 +43,27 @@ class AdService {
4443
_logger.info('AdService initialized.');
4544
}
4645

47-
/// Retrieves a loaded inline ad (native or banner) wrapped as an [AdFeedItem].
46+
/// Retrieves a loaded inline ad (native or banner) for display in a feed.
4847
///
4948
/// This method delegates the ad loading to the appropriate [AdProvider]
5049
/// based on the [adConfig]'s `primaryAdPlatform` and the requested [adType].
51-
/// If an ad is successfully loaded, it's wrapped in an [AdFeedItem]
52-
/// with a unique ID for display in content feeds.
5350
///
54-
/// Returns an [AdFeedItem] if an inline ad is available, otherwise `null`.
51+
/// Returns an [InlineAd] if an inline ad is available, otherwise `null`.
5552
///
5653
/// - [adConfig]: The remote configuration for ad display rules.
5754
/// - [adType]: The specific type of inline ad to load ([AdType.native] or [AdType.banner]).
5855
/// - [adThemeStyle]: UI-agnostic theme properties for ad styling.
59-
Future<AdFeedItem?> getInlineAd({
56+
Future<InlineAd?> getFeedAd({
6057
required AdConfig adConfig,
6158
required AdType adType,
6259
required AdThemeStyle adThemeStyle,
6360
}) async {
64-
if (!adConfig.enabled) {
65-
_logger.info('Ads are globally disabled in RemoteConfig.');
66-
return null;
67-
}
68-
69-
// Ensure the requested adType is valid for inline ads.
70-
if (adType != AdType.native && adType != AdType.banner) {
71-
_logger.warning(
72-
'getInlineAd called with unsupported AdType: $adType. '
73-
'Expected AdType.native or AdType.banner.',
74-
);
75-
return null;
76-
}
77-
78-
final primaryAdPlatform = adConfig.primaryAdPlatform;
79-
final adProvider = _adProviders[primaryAdPlatform];
80-
81-
if (adProvider == null) {
82-
_logger.warning('No AdProvider found for platform: $primaryAdPlatform');
83-
return null;
84-
}
85-
86-
final platformAdIdentifiers =
87-
adConfig.platformAdIdentifiers[primaryAdPlatform];
88-
if (platformAdIdentifiers == null) {
89-
_logger.warning(
90-
'No AdPlatformIdentifiers found for platform: $primaryAdPlatform',
91-
);
92-
return null;
93-
}
94-
95-
final adId = switch (adType) {
96-
AdType.native => platformAdIdentifiers.feedNativeAdId,
97-
AdType.banner => platformAdIdentifiers.feedBannerAdId,
98-
_ => null, // Handled by the initial adType check
99-
};
100-
101-
if (adId == null || adId.isEmpty) {
102-
_logger.warning(
103-
'No ad ID configured for platform $primaryAdPlatform and ad type $adType',
104-
);
105-
return null;
106-
}
107-
108-
_logger.info(
109-
'Requesting $adType ad from $primaryAdPlatform AdProvider with ID: $adId',
61+
return _loadInlineAd(
62+
adConfig: adConfig,
63+
adType: adType,
64+
adThemeStyle: adThemeStyle,
65+
feedAd: true,
11066
);
111-
try {
112-
InlineAd? loadedAd; // Use the new InlineAd abstract type
113-
switch (adType) {
114-
case AdType.native:
115-
loadedAd = await adProvider.loadNativeAd(
116-
adPlatformIdentifiers: platformAdIdentifiers,
117-
adId: adId,
118-
adThemeStyle: adThemeStyle,
119-
);
120-
case AdType.banner:
121-
loadedAd = await adProvider.loadBannerAd(
122-
adPlatformIdentifiers: platformAdIdentifiers,
123-
adId: adId,
124-
adThemeStyle: adThemeStyle,
125-
);
126-
case AdType.interstitial:
127-
case AdType.video:
128-
// These types are not handled by getInlineAd.
129-
_logger.warning(
130-
'Attempted to load $adType ad using getInlineAd. This is not supported.',
131-
);
132-
return null;
133-
}
134-
135-
if (loadedAd != null) {
136-
_logger.info('$adType ad successfully loaded and wrapped.');
137-
return AdFeedItem(id: _uuid.v4(), inlineAd: loadedAd); // Use inlineAd
138-
} else {
139-
_logger.info('No $adType ad loaded by AdProvider.');
140-
return null;
141-
}
142-
} catch (e) {
143-
_logger.severe('Error getting $adType ad from AdProvider: $e');
144-
return null;
145-
}
14667
}
14768

14869
/// Retrieves a loaded full-screen interstitial ad.
@@ -235,10 +156,47 @@ class AdService {
235156
required AdConfig adConfig,
236157
required AdThemeStyle adThemeStyle,
237158
}) async {
238-
// Check if ads are globally enabled and specifically for articles.
239-
if (!adConfig.enabled || !adConfig.articleAdConfiguration.enabled) {
159+
return _loadInlineAd(
160+
adConfig: adConfig,
161+
adType: adConfig.articleAdConfiguration.defaultInArticleAdType,
162+
adThemeStyle: adThemeStyle,
163+
feedAd: false,
164+
);
165+
}
166+
167+
/// Private helper method to consolidate logic for loading inline ads (native/banner).
168+
///
169+
/// This method handles the common steps of checking ad enablement, selecting
170+
/// the ad provider, retrieving platform-specific ad identifiers, and calling
171+
/// the appropriate `loadNativeAd` or `loadBannerAd` method on the provider.
172+
///
173+
/// - [adConfig]: The remote configuration for ad display rules.
174+
/// - [adType]: The specific type of inline ad to load ([AdType.native] or [AdType.banner]).
175+
/// - [adThemeStyle]: UI-agnostic theme properties for ad styling.
176+
/// - [feedAd]: A boolean indicating if this is for a feed ad (true) or in-article ad (false).
177+
///
178+
/// Returns an [InlineAd] if an ad is successfully loaded, otherwise `null`.
179+
Future<InlineAd?> _loadInlineAd({
180+
required AdConfig adConfig,
181+
required AdType adType,
182+
required AdThemeStyle adThemeStyle,
183+
required bool feedAd,
184+
}) async {
185+
// Check if ads are globally enabled and specifically for the context (feed or article).
186+
if (!adConfig.enabled ||
187+
(feedAd && !adConfig.feedAdConfiguration.enabled) ||
188+
(!feedAd && !adConfig.articleAdConfiguration.enabled)) {
240189
_logger.info(
241-
'In-article ads are disabled in RemoteConfig, either globally or for articles.',
190+
'Inline ads are disabled in RemoteConfig, either globally or for this context.',
191+
);
192+
return null;
193+
}
194+
195+
// Ensure the requested adType is valid for inline ads.
196+
if (adType != AdType.native && adType != AdType.banner) {
197+
_logger.warning(
198+
'_loadInlineAd called with unsupported AdType: $adType. '
199+
'Expected AdType.native or AdType.banner.',
242200
);
243201
return null;
244202
}
@@ -260,24 +218,25 @@ class AdService {
260218
return null;
261219
}
262220

263-
// Determine the ad type and ID from the article-specific configuration.
264-
final articleAdConfig = adConfig.articleAdConfiguration;
265-
final adType = articleAdConfig.defaultInArticleAdType;
266-
final adId = switch (adType) {
267-
AdType.native => platformAdIdentifiers.inArticleNativeAdId,
268-
AdType.banner => platformAdIdentifiers.inArticleBannerAdId,
269-
_ => null, // Should not happen due to AdConfig assertion
270-
};
221+
final adId = feedAd
222+
? (adType == AdType.native
223+
? platformAdIdentifiers.feedNativeAdId
224+
: platformAdIdentifiers.feedBannerAdId)
225+
: (adType == AdType.native
226+
? platformAdIdentifiers.inArticleNativeAdId
227+
: platformAdIdentifiers.inArticleBannerAdId);
271228

272229
if (adId == null || adId.isEmpty) {
273230
_logger.warning(
274-
'No in-article ad ID configured for platform $primaryAdPlatform and ad type $adType',
231+
'No ad ID configured for platform $primaryAdPlatform and ad type $adType '
232+
'for ${feedAd ? 'feed' : 'in-article'} placement.',
275233
);
276234
return null;
277235
}
278236

279237
_logger.info(
280-
'Requesting in-article $adType ad from $primaryAdPlatform AdProvider with ID: $adId',
238+
'Requesting $adType ad from $primaryAdPlatform AdProvider with ID: $adId '
239+
'for ${feedAd ? 'feed' : 'in-article'} placement.',
281240
);
282241
try {
283242
InlineAd? loadedAd;
@@ -297,20 +256,20 @@ class AdService {
297256
case AdType.interstitial:
298257
case AdType.video:
299258
_logger.warning(
300-
'Attempted to load $adType ad using getInArticleAd. This is not supported.',
259+
'Attempted to load $adType ad using _loadInlineAd. This is not supported.',
301260
);
302261
return null;
303262
}
304263

305264
if (loadedAd != null) {
306-
_logger.info('In-article $adType ad successfully loaded.');
265+
_logger.info('$adType ad successfully loaded.');
307266
return loadedAd;
308267
} else {
309-
_logger.info('No in-article $adType ad loaded by AdProvider.');
268+
_logger.info('No $adType ad loaded by AdProvider.');
310269
return null;
311270
}
312271
} catch (e) {
313-
_logger.severe('Error getting in-article $adType ad from AdProvider: $e');
272+
_logger.severe('Error getting $adType ad from AdProvider: $e');
314273
return null;
315274
}
316275
}

0 commit comments

Comments
 (0)