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

Android实现每2篇博客后插入Firebase实时数据库广告

问题背景

我有如下结构的Firebase实时数据库,根节点包含blog_posts和Ads两个子节点:

root
├─ blog_posts
│  ├─ post_id_1
│  │  ├─ title: "Blog Post 1"
│  │  ├─ content: "Content of Blog Post 1"
│  │  ├─ contentType: "text"
│  │  └─ contentUrl: "https://example.com/post1"
│  ├─ post_id_2
│  │  ├─ title: "Blog Post 2"
│  │  ├─ content: "Content of Blog Post 2"
│  │  ├─ contentType: "text"
│  │  └─ contentUrl: "https://example.com/post2"
│  ├─ post_id_3
│  │  ├─ title: "Blog Post 3 "
│  │  ├─ content: "Content of Blog Post 3"
│  │  ├─ contentType: "text"
│  │  └─ contentUrl: "https://example.com/post3"
│  └─ post_id_4
│     ├─ title: "Blog Post 4"
│     ├─ content: "Content of Blog Post 4"
│     ├─ contentType: "text"
│     └─ contentUrl: "https://example.com/post4"
└─ Ads
   ├─ ad_id_1
   │  ├─ title: "Ad 1"
   │  ├─ content: "Content of Ad 1"
   │  ├─ contentType: "image"
   │  └─ contentUrl: "https://example.com/ad1"
   └─ ad_id_2
      ├─ title: "Ad 2"
      ├─ content: "Content of Ad 2"
      ├─ contentType: "image"
      └─ contentUrl: "https://example.com/ad2"
需求与问题

我要实现每展示2篇博客文章后插入一条广告(比如Ad1在Post2后、Ad2在Post4后、Ad3在Post6后),但现在运行代码后,所有广告都显示在所有博客文章之后。

现有代码

MainActivityViewPost类

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import omega.jschii.healourlandafrica.R;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;

public class MainActivityViewPost extends AppCompatActivity {
    private RecyclerView recyclerView;
    private Adapter adapter;
    private List<Object> items;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_view_post);

        recyclerView = findViewById(R.id.recyclerView);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        items = new ArrayList<>();

        DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
        databaseReference.child("blog_posts").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    BlogPost blogPost = snapshot.getValue(BlogPost.class);
                    items.add(blogPost);
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                // Handle database error
            }
        });

        databaseReference.child("Ads").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    Ads ad = snapshot.getValue(Ads.class);
                    items.add(ad);
                }
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                // Handle database error
            }
        });
        adapter = new Adapter(this, items);
        recyclerView.setAdapter(adapter);
    }
}

Adapter类

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;

public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_BLOG_POST = 0;
private static final int VIEW_TYPE_AD = 1;

private List<Object> items;
private Context context;

// Constructor
public Adapter(Context context, List<Object> items) {
    this.context = context;
    this.items = items;
}

@Override
public int getItemViewType(int position) {
    Object item = items.get(position);
    return item instanceof BlogPost ? VIEW_TYPE_BLOG_POST : VIEW_TYPE_AD;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    if (viewType == VIEW_TYPE_BLOG_POST) {
        View itemView = inflater.inflate(R.layout.item_blog_post, parent, false);
        return new BlogPostViewHolder(itemView);
    } else {
        View itemView = inflater.inflate(R.layout.item_ad, parent, false);
        return new AdViewHolder(itemView);
    }
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof BlogPostViewHolder) {
        BlogPostViewHolder blogPostViewHolder = (BlogPostViewHolder) holder;
        BlogPost blogPost = (BlogPost) items.get(position);
        blogPostViewHolder.bind(blogPost);
    } else if (holder instanceof AdViewHolder) {
        AdViewHolder adViewHolder = (AdViewHolder) holder;
        Ads ad = (Ads) items.get(position);
        adViewHolder.bind(ad);
    }
}

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

// ViewHolder classes for blog posts and ads
private class BlogPostViewHolder extends RecyclerView.ViewHolder {
    private TextView titleTextView;

    BlogPostViewHolder(@NonNull View itemView) {
        super(itemView);
        titleTextView = itemView.findViewById(R.id.titleTextView);
    }

    void bind(BlogPost blogPost) {
        titleTextView.setText(blogPost.getTitle());
    }
}

private class AdViewHolder extends RecyclerView.ViewHolder {
    private TextView titleTextView;

    AdViewHolder(@NonNull View itemView) {
        super(itemView);
        titleTextView = itemView.findViewById(R.id.titleTextView);

    }

    void bind(Ads ad) {
        titleTextView.setText(ad.getTitle());

    }
}
}
解决方案

问题出在你把所有博客先加到列表,再把所有广告追加到后面,自然会出现广告全在末尾的情况。要实现每2篇博客插广告,得先分别存储博客和广告列表,等两个数据都加载完成后,再按规则合并成最终列表。

修改MainActivityViewPost类,具体改动如下:

  1. 新增两个列表分别存储博客和广告,替换原来直接用items的方式
  2. 用计数器跟踪两个数据请求的完成状态,确保都加载完再合并
  3. 编写合并逻辑:每添加2篇博客就插入一条广告,广告循环使用(如果广告数量不足,重复现有广告)

修改后的MainActivityViewPost代码:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import omega.jschii.healourlandafrica.R;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;

public class MainActivityViewPost extends AppCompatActivity {
    private RecyclerView recyclerView;
    private Adapter adapter;
    private List<Object> items;
    // 新增两个列表分别存储博客和广告
    private List<BlogPost> blogPosts;
    private List<Ads> adsList;
    // 计数器跟踪数据加载完成数
    private int dataLoadedCount = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_view_post);

        recyclerView = findViewById(R.id.recyclerView);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        items = new ArrayList<>();
        blogPosts = new ArrayList<>();
        adsList = new ArrayList<>();

        adapter = new Adapter(this, items);
        recyclerView.setAdapter(adapter);

        DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
        
        // 加载博客数据
        databaseReference.child("blog_posts").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    BlogPost blogPost = snapshot.getValue(BlogPost.class);
                    blogPosts.add(blogPost);
                }
                dataLoadedCount++;
                checkAndMergeData();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                // Handle database error
                dataLoadedCount++;
                checkAndMergeData();
            }
        });

        // 加载广告数据
        databaseReference.child("Ads").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    Ads ad = snapshot.getValue(Ads.class);
                    adsList.add(ad);
                }
                dataLoadedCount++;
                checkAndMergeData();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                // Handle database error
                dataLoadedCount++;
                checkAndMergeData();
            }
        });
    }

    // 检查数据是否全部加载完成,完成则合并列表
    private void checkAndMergeData() {
        if (dataLoadedCount != 2) {
            return;
        }

        items.clear();
        int adIndex = 0;
        int adCount = adsList.size();
        if (adCount == 0) {
            // 如果没有广告,直接添加所有博客
            items.addAll(blogPosts);
            adapter.notifyDataSetChanged();
            return;
        }

        // 按规则合并博客和广告
        for (int i = 0; i < blogPosts.size(); i++) {
            items.add(blogPosts.get(i));
            // 每2篇博客后插入广告(注意i从0开始,所以i+1是第N篇)
            if ((i + 1) % 2 == 0) {
                items.add(adsList.get(adIndex));
                adIndex = (adIndex + 1) % adCount; // 循环使用广告
            }
        }

        adapter.notifyDataSetChanged();
    }
}

Adapter类不需要修改,它已经支持两种视图类型的判断和绑定逻辑。

这样修改后,就能实现每2篇博客文章后插入一条广告的效果,广告会循环使用(比如Ad1、Ad2、Ad1、Ad2...这样依次插入)。

内容的提问来源于stack exchange,提问作者F.joel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 13:10:57