You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Compose LazyColumn如何避免广告Composable重加载?

在Compose LazyColumn中保留广告实例避免重复加载

在LazyColumn混合展示普通条目与广告时,滚动操作会导致广告Composable重组,进而触发广告重复加载。要保留同一广告实例、避免重复加载是可以实现的,核心是让广告的状态和View实例被稳定持有,不随LazyColumn的条目回收/复用而重建。

解决步骤及代码修改

1. 确保广告项使用稳定唯一的Key

LazyColumn的items函数中,广告项的key必须是唯一且稳定的标识(比如广告的unitId),这样滚动时LazyColumn不会销毁重建广告Composable,而是复用已有实例。这一步你已经做了,但要确保unitId不会随条目状态变化而改变。

2. 用remember稳定持有广告View实例

将广告View的创建逻辑放在remember块中,确保仅在Composable首次创建时执行一次,后续重组不会重复创建View和触发广告加载。注意不需要用mutableStateOf持有View实例——它是固定的引用,remember足够保证其稳定性。

3. 控制广告加载时机

广告的loadAd操作仅在View首次创建时执行,避免后续重组重复触发。

修改后的完整代码

LazyColumn部分

LazyColumn() {
    items(list, key = { it.unitId }) { item ->
        when (item) {
            is ListItem.NormalItem -> NormalItem()
            is ListItem.Advertisement -> AdvertisementAndroidView(item.advertisementData)
        }
    }
}

广告Composable部分

@Composable
fun AdvertisementAndroidView(advertisementData: AdvertisementData) {
    val context = LocalContext.current
    var isLoaded by remember { mutableStateOf(false) }

    // 仅在首次创建或广告数据变化时,才重新创建广告View
    val bannerView = remember(advertisementData) {
        createAdView(context, advertisementData) {
            isLoaded = true
        }
    }

    // 确保Composable销毁时,正确回收广告资源
    DisposableEffect(bannerView) {
        onDispose {
            bannerView.destroy()
        }
    }

    Box {
        if (!isLoaded) {
            AdvertisementPlaceHolder()
        } else {
            // 直接返回已创建的bannerView,不重复实例化
            AndroidView(factory = { bannerView })
        }
    }
}

private fun createAdView(
    context: Context,
    data: AdvertisementData,
    onAdLoaded: () -> Unit
): AdManagerAdView {
    val view = AdManagerAdView(context).apply {
        adUnitId = data.unitId
        // 配置广告尺寸、格式等参数
        adListener = object : AdListener() {
            override fun onAdLoaded() {
                super.onAdLoaded()
                onAdLoaded()
            }
        }
    }
    val adRequest = AdRequest.Builder().build()
    view.loadAd(adRequest)
    return view
}

关键说明

  • remember(advertisementData):添加广告数据作为依赖,仅当广告位更换、数据变化时才重新创建View,兼顾业务灵活性与实例稳定性。
  • DisposableEffect:在Composable被销毁时调用bannerView.destroy(),符合Android广告View的生命周期管理规范,避免内存泄漏。
  • 广告加载状态由isLoaded控制,仅在广告真正加载完成后才切换显示广告View,占位符逻辑保持不变。

如果需要手动刷新广告,不要依赖Compose重组,而是单独实现刷新逻辑(比如添加刷新按钮),手动调用bannerView.loadAd(adRequest)即可。

内容的提问来源于stack exchange,提问作者Harrienak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:40:42