如何在Jetpack Compose中展示MainActivity加载的RewardedInterstitial广告?
问题原因及解决方案
问题根源
你在Composable中直接通过MainActivity.rewardedInterstitialAd访问广告实例是错误的——rewardedInterstitialAd是MainActivity的非静态成员变量,每个Activity实例都有自己的副本,而你通过类名访问相当于试图读取一个不存在的静态变量,自然会得到null。
正确解决方案
推荐使用ViewModel来管理广告实例,这是Jetpack生态中跨UI组件共享状态的标准方式,也能避免Activity实例引用导致的内存泄漏问题。
步骤1:创建广告管理ViewModel
import android.app.Application import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData import com.google.android.gms.ads.AdRequest import com.google.android.gms.ads.LoadAdError import com.google.android.gms.ads.RewardedInterstitialAd import com.google.android.gms.ads.RewardedInterstitialAdLoadCallback class AdViewModel(application: Application) : AndroidViewModel(application) { val rewardedInterstitialAd = MutableLiveData<RewardedInterstitialAd?>() private val TAG = "AdViewModel" fun loadRewardedInterstitialAd() { RewardedInterstitialAd.load( getApplication(), "ca-app-pub-3940256099942544/5354046379", AdRequest.Builder().build(), object : RewardedInterstitialAdLoadCallback() { override fun onAdLoaded(ad: RewardedInterstitialAd) { rewardedInterstitialAd.value = ad } override fun onAdFailedToLoad(adError: LoadAdError) { rewardedInterstitialAd.value = null } } ) } }
步骤2:在MainActivity中初始化ViewModel并加载广告
class MainActivity : ComponentActivity() { private lateinit var adViewModel: AdViewModel private val TAG = "MainActivity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) adViewModel = ViewModelProvider(this)[AdViewModel::class.java] setContent { MyBeautyAppInJetpackComposeTheme { MyNavGraph() MobileAds.initialize(this) { adViewModel.loadRewardedInterstitialAd() } } } } }
步骤3:在Composable中使用ViewModel获取广告实例
@Composable fun RewardedShowCompose(actions: MainActions, maskArg: String) { val context = LocalContext.current val adViewModel = viewModel<AdViewModel>() // 用remember保存状态,避免重组时重置 val loading = remember { mutableStateOf(true) } Surface(modifier = Modifier.fillMaxSize()) { adViewModel.rewardedInterstitialAd.observeAsState().value?.let { ad -> ad.show(context as Activity) { actions.gotoFinalShow.invoke(maskArg) // 广告展示后清空实例,避免重复展示 adViewModel.rewardedInterstitialAd.value = null // 可在此触发下一次广告加载,方便后续使用 adViewModel.loadRewardedInterstitialAd() } } } }
备选方案(不推荐,仅作参考)
如果暂时不想引入ViewModel,也可以通过LocalContext获取当前MainActivity实例,再访问其成员变量,但要注意类型转换的安全性:
修改MainActivity的变量为可访问
class MainActivity : ComponentActivity(){ var rewardedInterstitialAd: RewardedInterstitialAd? = null // ... 其他代码不变 }
在Composable中获取Activity实例
@Composable fun RewardedShowCompose(actions: MainActions, maskArg: String) { val context = LocalContext.current val loading = remember { mutableStateOf(true) } val mainActivity = context as? MainActivity Surface(modifier = Modifier.fillMaxSize()) { mainActivity?.rewardedInterstitialAd?.let { ad -> ad.show(mainActivity) { actions.gotoFinalShow.invoke(maskArg) mainActivity.rewardedInterstitialAd = null mainActivity.loadAd() } } } }
注意:这种方式直接持有Activity引用,容易导致内存泄漏,不推荐在生产环境使用。
内容的提问来源于stack exchange,提问作者razi
相关产品推荐
相关产品推荐

