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

RecyclerView中Native ads随机出现 无法实现每9位后插入且排除首位的规则

问题排查

你遇到的广告随机出现的问题由以下几个错误导致:

  • 缺少ViewHolder复用的隐藏逻辑:你只在满足条件时把广告模板设为可见,没有在非广告位置的分支里将模板隐藏,滑出屏幕的Holder被复用到其他位置时,之前加载的广告还会保留显示,就会出现随机位置出广告的问题。
  • 广告异步加载错位:AdLoader加载广告是异步操作,等广告加载完成回调时,当前Holder可能已经被复用到其他列表位置,这时给Holder设置广告就会加载到错误的位置。
  • 列表位置计算逻辑有隐患:你当前直接用Adapter的position做判断,后续如果新增广告导致列表总长度变化时,内容项和广告位的对应关系会紊乱,同时你将MobileAds.initialize(context)放在onBindViewHolder里重复调用,会严重拖慢列表滑动性能,该方法只需要在应用启动时初始化一次即可。

修复方案

1. 新增辅助计算方法,区分广告位和内容位

在Adapter中新增以下常量和工具方法,提前计算好广告位置和内容项的对应关系:

// 你的原始内容列表,不要混入广告数据
private var contentList: List<你的内容数据类型> = emptyList()

// 计算列表总长度:每9个内容加1个广告
override fun getItemCount(): Int {
    val contentSize = contentList.size
    return if (contentSize == 0) 0 else contentSize + (contentSize / 9)
}

// 计算当前Adapter位置对应的原始内容列表索引,排除广告占用的位置
private fun getRealContentPosition(adapterPosition: Int): Int {
    val adCountBefore = if (adapterPosition == 0) 0 else adapterPosition / 9
    return adapterPosition - adCountBefore
}

2. 完善onBindViewHolder逻辑,处理复用和异步加载错位问题

修改你的绑定逻辑,新增非广告位的隐藏分支,同时给Holder加Tag校验防止广告加载错位:

override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
    // 判断当前位置是否为广告位
    if (position > 0 && position % 9 == 0) {
        holder.templateView.visibility = View.VISIBLE
        // 给Holder加标记,广告加载完成后校验是否还在当前位置
        holder.itemView.tag = position
        
        val adLoader = AdLoader.Builder(context, "ca-app-pub-xxxxxxxxxxxxxxxx/yyyyyyyyy")
            .forNativeAd { nativeAd ->
                // 只有Holder还在当前广告位时才赋值,防止错位
                if (holder.itemView.tag == position) {
                    val style = NativeTemplateStyle.Builder()
                        .withMainBackgroundColor(ColorDrawable(Color.WHITE))
                        .build()
                    holder.templateView.setStyles(style)
                    holder.templateView.setNativeAd(nativeAd)
                }
            }.build()
        adLoader.loadAd(AdRequest.Builder().build())
    } else {
        // 非广告位必须隐藏广告模板,处理复用问题
        holder.templateView.visibility = View.GONE
        // 绑定你的正常内容逻辑,用getRealContentPosition拿原始内容数据
        val contentData = contentList[getRealContentPosition(position)]
        // 给Holder的内容控件赋值的原有逻辑
    }
}

3. 迁移广告SDK初始化逻辑

把MobileAds.initialize(context)代码移到Application或者当前页Activity的onCreate方法中,不要在Adapter里重复调用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:24:07