如何在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
相关产品推荐
相关产品推荐

