Jetpack Compose中安全获取Activity的方案?广告管理器适配难题
问题:Jetpack Compose+Hilt集成插屏广告管理器的Activity获取问题
我在Jetpack Compose应用中实现了处理插屏广告的InterstitialAdManager类,代码如下:
class InterstitialAdManager(private val context: Context) { private var mInterstitialAd: InterstitialAd? = null private var lastLoadedUnitAd: String? = null init { loadInterstitial() } private fun loadInterstitial() { InterstitialAd.load( context, lastLoadedUnitAd.orEmpty(), AdRequest.Builder().build(), object : InterstitialAdLoadCallback() { override fun onAdFailedToLoad(adError: LoadAdError) { mInterstitialAd = null } override fun onAdLoaded(interstitialAd: InterstitialAd) { mInterstitialAd = interstitialAd } } ) } fun showInterstitial( onAdDismissed: () -> Unit = {}, onAdShowedFullScreen: () -> Unit = {} ) { val activity = context.findActivity() if (mInterstitialAd != null && activity != null) { mInterstitialAd?.fullScreenContentCallback = object : FullScreenContentCallback() { override fun onAdFailedToShowFullScreenContent(e: AdError) { mInterstitialAd = null onAdDismissed() } override fun onAdDismissedFullScreenContent() { mInterstitialAd = null loadInterstitial() onAdDismissed() } override fun onAdShowedFullScreenContent() { onAdShowedFullScreen() } } mInterstitialAd?.show(activity) } else { onAdDismissed() } } fun removeInterstitial() { mInterstitialAd?.fullScreenContentCallback = null mInterstitialAd = null } fun setAdUnit(unitAd: String) { lastLoadedUnitAd = unitAd loadInterstitial() } private fun Context.findActivity(): Activity? = when (this) { is Activity -> this is ContextWrapper -> baseContext.findActivity() else -> null } }
该类在XML开发中运行正常,但在Jetpack Compose结合Hilt注入时遇到问题:
我通过DetailState管理状态:
data class DetailState( val interstitialAdManager: InterstitialAdManager? = null, val currentDesign: Design? = null )
并在ViewModel中注入广告管理器:
@HiltViewModel class DetailViewModel @Inject constructor(interstitialAdManager: InterstitialAdManager, ) : ViewModel() { var state by mutableStateOf(DetailState()) private set init { state = state.copy(interstitialAdManager = interstitialAdManager) state.interstitialAdManager?.setAdUnit("hidden_unit_ad") } }
最初的Hilt模块提供Application Context:
@Module @InstallIn(SingletonComponent::class) class AdsModule { @Provides @Singleton fun interstitialAdManagerProvider(@ApplicationContext context: Context) = InterstitialAdManager(context) }
这导致管理器的findActivity方法无法找到Activity。
尝试将模块改为ActivityComponent的ActivityScoped:
@Module @InstallIn(ActivityComponent::class) class AdsModule { @Provides @ActivityScoped fun interstitialAdManagerProvider(@ActivityContext context: Context) = InterstitialAdManager(context) }
但因ViewModel与Activity组件范围不匹配出现编译错误。
目前可行但不够安全的方案是在showInterstitial方法中传入Activity,通过val activity = LocalContext.current as Activity获取,希望得到更优的实现方案。
内容的提问来源于stack exchange,提问作者Ludiras
相关产品推荐
相关产品推荐

