如何在RecyclerView中每3条Firebase活动后插入另一引用的广告数据
实现方案
1 前置准备
- 创建
AdModel实体类,和Firebase中Ads节点的字段一一对应,包含广告需要展示的所有属性(如广告标题、宣传图链接、跳转目标等) - 新建广告布局文件
R.layout.ad_cards,和你现有的活动卡片布局逻辑保持一致,定义广告需要的控件 - 创建
AdViewHolder类,继承RecyclerView.ViewHolder,绑定广告布局的控件
2 提前加载广告数据
在Activity的onCreate方法中先加载所有广告数据存入本地列表,避免后续重复请求:
private List<AdModel> mAdList = new ArrayList<>(); // 放在onCreate里执行 ads_reference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { mAdList.clear(); for (DataSnapshot ds : snapshot.getChildren()) { AdModel ad = ds.getValue(AdModel.class); if (ad != null) { mAdList.add(ad); } } // 广告加载完成后再初始化/刷新活动列表适配器 initEventAdapter(); } @Override public void onCancelled(@NonNull DatabaseError error) { // 加载失败直接初始化活动适配器,不插入广告 initEventAdapter(); } });
3 自定义多类型RecyclerView适配器
替换原来的FirebaseRecyclerAdapter,改为自定义的多类型适配器,实现按规则插入广告的逻辑:
public class EventAdAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int TYPE_EVENT = 0; private static final int TYPE_AD = 1; private List<EventModel> mEventList; private List<AdModel> mAdList; private Context mContext; public EventAdAdapter(Context context, List<EventModel> eventList, List<AdModel> adList) { this.mContext = context; this.mEventList = eventList; this.mAdList = adList; } @Override public int getItemViewType(int position) { // 每4个位置的最后一个是广告,0、1、2是活动,3是广告,4、5、6活动,7广告,以此类推 if ((position + 1) % 4 == 0 && !mAdList.isEmpty()) { return TYPE_AD; } return TYPE_EVENT; } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == TYPE_AD) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.ad_cards, parent, false); return new AdViewHolder(view); } else { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.event_cards, parent, false); return new EventViewHolder(view); } } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if (getItemViewType(position) == TYPE_AD) { // 绑定广告数据,广告数量不够时循环取 int adIndex = (position / 4) % mAdList.size(); AdModel ad = mAdList.get(adIndex); AdViewHolder adHolder = (AdViewHolder) holder; // 这里写你自己的广告控件绑定逻辑,比如加载图片、设置标题、点击跳转等 Glide.with(mContext).load(ad.getAdImage()).into(adHolder.adPoster); } else { // 计算当前位置对应的活动索引:减去前面已经插入的广告数量 int adCountBefore = position / 4; int eventPosition = position - adCountBefore; EventModel event = mEventList.get(eventPosition); EventViewHolder eventHolder = (EventViewHolder) holder; // 这里直接复制你原来FirebaseRecyclerAdapter的onBindViewHolder里的活动绑定逻辑即可 StringBuilder date_time = new StringBuilder() .append(event.getEventDate()) .append(": ") .append(event.getEventTime()); eventHolder.eventName.setText(event.getEventName()); eventHolder.eventDate.setText(date_time); eventHolder.eventVenue.setText(event.getEventVenue()); Glide.with(mContext) .load(event.getEventPoster()) .into(eventHolder.eventPoster); // 其余头像加载、点击事件逻辑都和你原来的写法完全一致 } } @Override public int getItemCount() { if (mAdList.isEmpty()) { return mEventList.size(); } // 总条目数=活动数+插入的广告数,广告数为活动数/3向下取整 int adCount = mEventList.size() / 3; return mEventList.size() + adCount; } // 提供对外方法,活动数据更新时刷新列表 public void updateEventList(List<EventModel> newEventList) { this.mEventList = newEventList; notifyDataSetChanged(); } }
4 初始化活动数据并绑定适配器
把你原来onStart里的FirebaseRecyclerAdapter逻辑替换成监听活动数据更新,刷新自定义适配器即可:
private List<EventModel> mEventList = new ArrayList<>(); private EventAdAdapter mAdapter; private void initEventAdapter() { mAdapter = new EventAdAdapter(HomeActivity.this, mEventList, mAdList); mRecyclerView.setAdapter(mAdapter); // 监听活动节点的实时更新 event_reference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { mEventList.clear(); for (DataSnapshot ds : snapshot.getChildren()) { EventModel event = ds.getValue(EventModel.class); if (event != null) { mEventList.add(event); } } mAdapter.notifyDataSetChanged(); // 原来的进度条隐藏逻辑放这里 } @Override public void onCancelled(@NonNull DatabaseError error) { } }); }
注意事项
- 如果需要保留FirebaseUI的分页加载、增量更新能力,可以不用自己全量监听活动节点,而是对原有的
FirebaseRecyclerAdapter做包装,在自定义适配器中调用原适配器的对应方法获取活动数据即可,核心的位置计算逻辑和上面的方案完全一致 - 广告列表为空或者广告数量不足时,上面的代码已经做了兼容处理,不会出现空指针问题
- 如果不需要循环展示广告,广告数量用完后就不再插入,可以修改
getItemViewType的判断逻辑,加上(position/4) < mAdList.size()的条件即可
内容的提问来源于stack exchange,提问作者Developer Sam
相关产品推荐
相关产品推荐

