-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
I have a RecyclerView, and I aim to insert a banner ad after every 10 items within it. However, following the approach outlined in the official documentation leads to a decrease in ad display rate when pre-loading ads. Specifically, I experience a significantly low display rate, approximately 20-30%.
Another approach involves loading the ad-containing holder either in onCreateViewHolder or its constructor. However, this method only loads one ad at a time.
Alternatively, I attempted to load ads in onBindViewHolder, as demonstrated in my example. However, this approach isn't optimal because the onLoading event occurs when the creative exits the screen during scrolling and re-enters it, triggering the bind operation again. I believe this could also violate policies.
In summary, none of these solutions prove effective. I seek a different and correct method that doesn't burden the RecyclerView with repeated loading during scrolling.
The current method of pre-loading ads is outdated and not entirely correct. If users don't scroll to the end of the list, they won't generate any views. Despite an 80-90% match rate, the display rate remains at 20%, which is inaccurate. I am in need of a solution to address this issue.
BannerRecyclerViewExample:
https://github.com/googleads/googleads-mobile-android-examples/blob/master/java/advanced/BannerRecyclerViewExample/app/src/main/java/com/google/android/gms/example/bannerrecyclerviewexample/MainActivity.java
InlineAdaptiveBannerExample:
https://github.com/googleads/googleads-mobile-android-examples/blob/main/java/advanced/InlineAdaptiveBannerExample/app/src/main/java/com/google/android/gms/example/inlineadaptivebannerexample/MainActivity.java
My example: (My approach is flawed because the banner ad gets removed and then reloaded when the RecyclerView screen exits.)
The official example is also incorrect. As I mentioned, although the ads are pre-loaded, they are not always displayed. Ideally, the RecyclerView should pause the bind/banner ad where there are no impressions and then resume, but I'm unsure how to implement this.
TestActivity
public class TestActivity extends AppCompatActivity {
RecyclerView recyclerView;
TestAdapter testAdapter;
List<String> itemList = new ArrayList<>();
@SuppressLint("SetTextI18n")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);
for (int i = 0; i < 200; i++) {
itemList.add("Item " + i);
if (i % 10 == 0) {
itemList.add(null);
}
}
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
testAdapter = new TestAdapter(itemList);
recyclerView.setAdapter(testAdapter);
}
}
TestAdapter
public class TestAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<String> itemList;
static final int CONTENT_TYPE = 0;
static final int AD_TYPE = 1;
public TestAdapter(List<String> itemList) {
this.itemList = itemList;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == CONTENT_TYPE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_item, parent, false);
return new ViewHolder(view);
} else {
View adView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_ad, parent, false);
return new AdRecyclerHolder(adView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ViewHolder viewHolder) {
viewHolder.idText.setText(String.valueOf(position));
viewHolder.title.setText(itemList.get(position));
} else if (holder instanceof AdRecyclerHolder adHolder) {
AdRequest adRequest = new AdRequest.Builder().build();
adHolder.mAdView.loadAd(adRequest);
adHolder.mAdView.setAdListener(new AdListener() {
@Override
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
Log.e("TAG_AD", "onAdFailedToLoad");
super.onAdFailedToLoad(loadAdError);
}
@Override
public void onAdLoaded() {
Log.e("TAG_AD", "onAdLoaded");
}
});
}
}
@Override
public int getItemCount() {
return itemList.size();
}
@Override
public int getItemViewType(int position) {
if (itemList.get(position) == null) {
return AD_TYPE;
} else {
return CONTENT_TYPE;
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView idText, title;
public ViewHolder(@NonNull View itemView) {
super(itemView);
idText = itemView.findViewById(R.id.id_text);
title = itemView.findViewById(R.id.title);
}
}
public static class AdRecyclerHolder extends RecyclerView.ViewHolder {
AdView mAdView;
public AdRecyclerHolder(@NonNull View itemView) {
super(itemView);
mAdView = itemView.findViewById(R.id.adView);
}
}
}