I have the following Firebase Realtime Database, which has parts inside the root:
1: blog_posts
2: 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_1
-
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"
- ad_id_1
What I want to achieve is to display Ads after every 2 blog posts.
But when I run my codes this is what comes as results( Ads appear after all posts).
Here is my code:
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 class
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());
}
}
}
here is the output
How can I make Ad 1 appear after post2, Ad2 appear after post4 , and Ad3 appear after post6
2
Answers
You can get that type of result by displaying ads after specific posts in a RecyclerView, you can modify the RecyclerView adapter to include logic for displaying ads at those positions.
Firebase json structure :
You’re getting this result:
Because you’re performing two separate Firebase Realtime Database requests, one after the other. If you need to have displayed 2 posts and an ad, 2 posts, and an ad, and so on, then you have to perform the request for getting the ads only when you already have the blog posts available. This means that when the operation for getting the ads is successful, then you’ll have two lists full of data, one list with blog posts and one list with ads. Now you can create a new list that combines the two lists in the way mentioned above.
You can achieve this by nesting the second request inside the callback of the first request, or you can use get() instead of addListenerForSingleValueEvent() and right after that use Tasks.whenAllSuccess(), as you can see below: