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

如何在Android的RecyclerView中使用Kotlin集成AdMob原生高级广告?

实现RecyclerView每5个条目插入AdMob原生高级广告的完整步骤

1. 配置项目依赖与清单文件

  • 在Module级别的build.gradle(或build.gradle.kts)中添加AdMob依赖:
dependencies {
    implementation 'com.google.android.gms:play-services-ads:22.6.0'
}
  • 在AndroidManifest.xml中添加必要权限和AdMob应用ID(测试阶段可使用官方测试ID):
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application ...>
    <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-3940256099942544~3347511713"/> <!-- 测试应用ID -->
</application>

2. 创建原生广告条目布局

新建res/layout/item_native_ad.xml,用于展示原生广告元素:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">

    <com.google.android.gms.ads.nativead.NativeAdView
        android:id="@+id/native_ad_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <com.google.android.gms.ads.nativead.MediaView
                android:id="@+id/ad_media"
                android:layout_width="120dp"
                android:layout_height="120dp"
                android:layout_marginEnd="16dp"/>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/ad_headline"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="16sp"
                    android:textStyle="bold"/>

                <TextView
                    android:id="@+id/ad_body"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="8dp"
                    android:textSize="14sp"/>

                <Button
                    android:id="@+id/ad_call_to_action"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="12dp"
                    android:background="@drawable/ad_button_bg"
                    android:textColor="@android:color/white"/>
            </LinearLayout>
        </LinearLayout>

        <com.google.android.gms.ads.nativead.AdChoicesView
            android:id="@+id/ad_choices"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top|end"
            ads:adChoicesImageSize="small"/>
    </com.google.android.gms.ads.nativead.NativeAdView>
</LinearLayout>

3. 实现RecyclerView Adapter

基础常量与初始化逻辑

public class MixedAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int TYPE_NORMAL_ITEM = 0;
    private static final int TYPE_AD_ITEM = 1;
    private List<Object> mMixedData; // 混合普通数据与广告占位符
    private List<NativeAd> mCachedAds = new ArrayList<>();
    private Context mContext;
    private final String AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110"; // 测试广告单元ID

    public MixedAdapter(Context context, List<String> originalData) {
        mContext = context;
        mMixedData = new ArrayList<>();
        // 插入广告占位:每5个普通条目后加一个(最后一个条目后不插)
        for (int i = 0; i < originalData.size(); i++) {
            mMixedData.add(originalData.get(i));
            if ((i + 1) % 5 == 0 && i != originalData.size() - 1) {
                mMixedData.add(null);
            }
        }
        // 预加载对应数量的广告
        loadNativeAds();
    }

加载原生广告

private void loadNativeAds() {
        NativeAdLoader adLoader = new NativeAdLoader.Builder(mContext, AD_UNIT_ID)
                .setNativeAdOptions(new NativeAdOptions.Builder().build())
                .forNativeAd(nativeAd -> {
                    mCachedAds.add(nativeAd);
                    notifyDataSetChanged();
                })
                .withAdListener(new AdListener() {
                    @Override
                    public void onAdFailedToLoad(LoadAdError error) {
                        // 广告加载失败可记录日志或重试
                    }
                })
                .build();

        // 加载与广告占位数量匹配的广告
        int adCount = (int) mMixedData.stream().filter(Objects::isNull).count();
        adLoader.loadAds(new AdRequest.Builder().build(), adCount);
    }

创建ViewHolder

// 普通条目ViewHolder
    static class NormalViewHolder extends RecyclerView.ViewHolder {
        TextView contentTv;
        NormalViewHolder(View itemView) {
            super(itemView);
            contentTv = itemView.findViewById(R.id.tv_normal_content);
        }
    }

    // 广告条目ViewHolder
    static class AdViewHolder extends RecyclerView.ViewHolder {
        NativeAdView adView;
        TextView headlineTv, bodyTv;
        MediaView mediaView;
        Button ctaBtn;

        AdViewHolder(View itemView) {
            super(itemView);
            adView = itemView.findViewById(R.id.native_ad_view);
            headlineTv = itemView.findViewById(R.id.ad_headline);
            bodyTv = itemView.findViewById(R.id.ad_body);
            mediaView = itemView.findViewById(R.id.ad_media);
            ctaBtn = itemView.findViewById(R.id.ad_call_to_action);

            // 绑定广告视图到NativeAdView
            adView.setHeadlineView(headlineTv);
            adView.setBodyView(bodyTv);
            adView.setMediaView(mediaView);
            adView.setCallToActionView(ctaBtn);
        }
    }

重写Adapter核心方法

@Override
    public int getItemViewType(int position) {
        return mMixedData.get(position) == null ? TYPE_AD_ITEM : TYPE_NORMAL_ITEM;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        if (viewType == TYPE_NORMAL_ITEM) {
            return new NormalViewHolder(inflater.inflate(R.layout.item_normal, parent, false));
        } else {
            return new AdViewHolder(inflater.inflate(R.layout.item_native_ad, parent, false));
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (getItemViewType(position) == TYPE_NORMAL_ITEM) {
            NormalViewHolder normalHolder = (NormalViewHolder) holder;
            normalHolder.contentTv.setText((String) mMixedData.get(position));
        } else {
            AdViewHolder adHolder = (AdViewHolder) holder;
            // 从缓存中取可用广告填充
            if (!mCachedAds.isEmpty()) {
                NativeAd nativeAd = mCachedAds.remove(0);
                populateAdView(nativeAd, adHolder.adView);
            }
        }
    }

    @Override
    public int getItemCount() {
        return mMixedData.size();
    }

    // 填充广告内容
    private void populateAdView(NativeAd nativeAd, NativeAdView adView) {
        adView.setNativeAd(nativeAd);
        headlineTv.setText(nativeAd.getHeadline());
        bodyTv.setText(nativeAd.getBody());
        ctaBtn.setText(nativeAd.getCallToAction());

        if (nativeAd.getMediaContent() != null) {
            mediaView.setMediaContent(nativeAd.getMediaContent());
        }
    }

    // 回收时销毁广告,避免内存泄漏
    @Override
    public void onViewRecycled(RecyclerView.ViewHolder holder) {
        if (holder instanceof AdViewHolder) {
            NativeAdView adView = ((AdViewHolder) holder).adView;
            NativeAd nativeAd = adView.getNativeAd();
            if (nativeAd != null) nativeAd.destroy();
        }
        super.onViewRecycled(holder);
    }
}

4. 初始化RecyclerView

在Activity/Fragment中配置RecyclerView:

// 构造普通测试数据
List<String> normalData = new ArrayList<>();
for (int i = 0; i < 20; i++) {
    normalData.add("普通条目 " + (i + 1));
}

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
MixedAdapter adapter = new MixedAdapter(this, normalData);
recyclerView.setAdapter(adapter);

注意事项

  • 测试阶段必须使用AdMob官方测试ID,避免触发政策违规。
  • 广告加载为异步操作,可添加加载占位视图优化用户体验。
  • 在Adapter销毁时需清理所有缓存的NativeAd,防止内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:09:58