Ads making recyclerview lag - android

I put banner ads from admob in my recyclerview and it lags my recyclerview when the user scrolls, here's my adapter code of the recyclerview I'm talking about. What could be wrong that it makes the recyclerview lag?
public class NewReleasesAdapter extends RecyclerView.Adapter< RecyclerView.ViewHolder> implements BillingProcessor.IBillingHandler {
public static final String TAG = NewReleasesAdapter.class.getSimpleName();
private LayoutInflater mInflater;
private Context mContext;
private List<Release> mNewReleases;
private DatabaseHelper mDatabaseHelper;
// A game/release item view type.
private static final int GAME_ITEM_VIEW_TYPE = 0;
// The banner ad view type.
private static final int BANNER_AD_VIEW_TYPE = 1;
// Billing
private BillingProcessor mBillingProcessor;
private boolean mIsProVersion;
// Ads
private AdRequest mAdRequest;
public NewReleasesAdapter(Context context) {
mContext = context;
mInflater = LayoutInflater.from(mContext);
mDatabaseHelper = DatabaseHelper.getDatabaseHelper(mContext);
mBillingProcessor = new BillingProcessor(
mContext,
"...",
this);
mBillingProcessor.initialize();
mBillingProcessor.loadOwnedPurchasesFromGoogle();
// Is in europe
if (ConsentInformation.getInstance(mContext).isRequestLocationInEeaOrUnknown()) {
switch (ConsentInformation.getInstance(mContext).getConsentStatus()) {
case PERSONALIZED:
// Personalized ads
mAdRequest = new AdRequest.Builder().build();
break;
case NON_PERSONALIZED:
// fall though to none Personalized ads
default:
// None Personalized ads
Bundle extras = new Bundle();
// npa is short for "none personalized ads"
extras.putString("npa", "1");
mAdRequest = new AdRequest.Builder()
.addNetworkExtrasBundle(AdMobAdapter.class, extras)
.build();
break;
}
} else {
// Personalized ads
mAdRequest = new AdRequest.Builder().build();
}
}
public void setNewReleases(List<Release> newReleases) {
this.mNewReleases = newReleases;
notifyDataSetChanged();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch(viewType) {
case GAME_ITEM_VIEW_TYPE:
return new NewGameHolder(mInflater.inflate(R.layout.newly_added_game, parent, false));
case BANNER_AD_VIEW_TYPE:
return new ViewHolderAdMob(mInflater.inflate(R.layout.list_item_ad, parent, false), mAdRequest);
default:
return new NewGameHolder(mInflater.inflate(R.layout.newly_added_game, parent, false));
}
}
#Override
public int getItemViewType(int position) {
// isn't pro version
if (mIsProVersion) {
if ((position + 1) % 4 == 0) {
return BANNER_AD_VIEW_TYPE;
}
}
return GAME_ITEM_VIEW_TYPE;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case BANNER_AD_VIEW_TYPE:
// nothing to do
break;
case GAME_ITEM_VIEW_TYPE:
// A lot of set texts
break;
}
}
#Override
public int getItemCount() {
if (mNewReleases == null) {
return 0;
}
return mNewReleases.size();
}
#Override
public void onProductPurchased(#NonNull String productId, #Nullable TransactionDetails details) {
}
#Override
public void onPurchaseHistoryRestored() {
}
#Override
public void onBillingError(int errorCode, #Nullable Throwable error) {
// Log.d(TAG, "Error: " + errorCode + " : " + error.getMessage());
}
#Override
public void onBillingInitialized() {
mBillingProcessor.loadOwnedPurchasesFromGoogle();
if (mBillingProcessor.isPurchased("gaming_reminder_pro")) {
mIsProVersion = true;
// Toast.makeText(mContext, "You're a pro user! Thanks!", Toast.LENGTH_SHORT).show();
} else {
// Show ads
mIsProVersion = false;
}
}
public BillingProcessor getBillingProcessor() {
return mBillingProcessor;
}
public static class NewGameHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView summary;
public TextView releaseDate;
public TextView platforms;
public TextView genres;
public ImageView cover;
public Button favorite;
public ProgressBar coverProgressBar;
public RelativeLayout newReleaseLayout;
public NewGameHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.game_name);
summary = itemView.findViewById(R.id.summary);
releaseDate = itemView.findViewById(R.id.release_date);
platforms = itemView.findViewById(R.id.platforms);
genres = itemView.findViewById(R.id.genres);
cover = itemView.findViewById(R.id.cover_image);
favorite = itemView.findViewById(R.id.favorite);
coverProgressBar = itemView.findViewById(R.id.cover_progress_bar);
newReleaseLayout = itemView.findViewById(R.id.new_release);
}
}
public static class ViewHolderAdMob extends RecyclerView.ViewHolder {
public AdView mAdView;
public ViewHolderAdMob(View view, final AdRequest adRequest) {
super(view);
mAdView = view.findViewById(R.id.adView);
if (adRequest != null) {
mAdView.loadAd(adRequest);
mAdView.setAdListener(new AdListener(){
#Override
public void onAdLoaded() {
mAdView.setVisibility(View.VISIBLE);
}
});
}
}
}
}
Some more helpful info: Generally, 4 banner ads are shown in this recyclerview and they are only shown for none-pro users. I have a pro iap (in app purchase) that removes the ads

It's best to show native ads in a recycler view as it's more customizable in every way. If you must show banner ads, I'd suggest to preload the adviews in an activity or a fragment, then add or show them in the recycler view as needed. ViewHolder isn't a good place to load ads.
You can follow this google provided example
https://github.com/googleads/googleads-mobile-android-examples/tree/master/java/advanced/BannerRecyclerViewExample

Related

How to efficiently loading native ads on demand with the recyclerview adapter?

What i am doing is, that i have a recyclerView which has it's adapter and from within adapter i am loading the nativeAds. But due to loading the ads within the recyclerView instead of preloading the ads my recyclerView is not scrolling smoothly.
And also i tried to load the native ad on different thread but that also was't helpful.
Any ideas how to load the native ad without sacrificing the performance??
public class GetInspiredAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static int VIEW_TYPE_ADS = 0;
public static int VIEW_TYPE_NOTADS = 1;
// this shows that the ad is to be added after this many items.
public static int ADS_AFTER_HOW_MANY_ITEMS = 3;
private boolean isNetworkAvailable = false;
private Context context;
private ArrayList<Object> list;
private GetInspiredListener listener;
public GetInspiredAdapter(Context context, ArrayList<Object> list, GetInspiredListener listener) {
this.context = context;
this.list = list;
this.listener = listener;
}
private void addNativeToList() {
int i = ADS_AFTER_HOW_MANY_ITEMS;
while (i < list.size()) {
list.add(i, new UnifiedNativeAdView(context));
i += ADS_AFTER_HOW_MANY_ITEMS + 1;
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_TYPE_ADS) {
View unifiedNativeLayoutView = LayoutInflater.from(context).inflate(R.layout.ad_unified, viewGroup, false);
unifiedNativeLayoutView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_ADS));
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
} else {
View itemView = LayoutInflater.from(context).inflate(R.layout.image_item, viewGroup, false);
itemView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_NOTADS));
return new GetInspiredViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
if (viewType == VIEW_TYPE_ADS) {
if (!isNetworkAvailable) {
list.remove(position);
notifyDataSetChanged();
return;
}
AdLoader.Builder builder = new AdLoader.Builder(context, Constants.INSPIRED_MOB)
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
populateNativeAdView(unifiedNativeAd, (UnifiedNativeAdViewHolder) holder);
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int i) {
super.onAdFailedToLoad(i);
}
});
builder.build().loadAd(new AdRequest.Builder().build());
} else if (viewType == VIEW_TYPE_NOTADS) {
LoadImage((InspiredObject) list.get(getItemIndex(position)), (GetInspiredViewHolder) holder);
}
}
private void LoadImage(InspiredObject obj, GetInspiredViewHolder viewHolder) {
//Url link to images
String url = "http://aim-itech.com/mandala/image/";
String string = url + obj.low;
Glide.with(context).load(string).override(Constants.SAMPLE_SIZE_MEDIUM).into(viewHolder.imageView);
Log.e("TAG", string);
}
private void populateNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdViewHolder holder) {
if (nativeAd == null) {
holder.getAdView().setVisibility(View.INVISIBLE);
holder.textLoading.setVisibility(View.VISIBLE);
return;
}
holder.textLoading.setVisibility(View.GONE);
UnifiedNativeAdView adView = holder.getAdView();
adView.setVisibility(View.VISIBLE);
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
public int getItemIndex(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
Object recyclerViewItem = list.get(getItemIndex(position));
if (recyclerViewItem instanceof UnifiedNativeAd) {
return VIEW_TYPE_ADS;
} else if (recyclerViewItem instanceof UnifiedNativeAdView) {
return VIEW_TYPE_ADS;
}
return VIEW_TYPE_NOTADS;
}
public boolean isNetworkAvailable() {
return isNetworkAvailable;
}
public void setNetworkAvailable(boolean networkAvailable) {
isNetworkAvailable = networkAvailable;
if (isNetworkAvailable) {
addNativeToList();
}
}
#Override
public int getItemCount() {
return list.size();
}
public class GetInspiredViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public GetInspiredViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageProf);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
InspiredObject inspiredObject = (InspiredObject) list.get(getAdapterPosition());
Intent i = new Intent(context, InspiredActivity.class);
i.putExtra("image", inspiredObject.high);
listener.onClick(i);
}
});
}
}
public class UnifiedNativeAdViewHolder extends RecyclerView.ViewHolder {
private UnifiedNativeAdView adView;
private TextView textLoading;
private CardView adContainer;
public UnifiedNativeAdView getAdView() {
return adView;
}
UnifiedNativeAdViewHolder(View view) {
super(view);
textLoading = view.findViewById(R.id.native_loading_text);
adView = view.findViewById(R.id.native_ad_view);
adContainer = view.findViewById(R.id.ad_unified_conatiner);
// The MediaView will display a video asset if one is present in the ad, and the
// first image asset otherwise.
adView.setMediaView((MediaView) adView.findViewById(R.id.ad_media));
// Register the view used for each individual asset.
adView.setHeadlineView(adView.findViewById(R.id.ad_headline));
adView.setBodyView(adView.findViewById(R.id.ad_body));
adView.setCallToActionView(adView.findViewById(R.id.ad_call_to_action));
adView.setIconView(adView.findViewById(R.id.ad_icon));
adView.setPriceView(adView.findViewById(R.id.ad_price));
adView.setStarRatingView(adView.findViewById(R.id.ad_stars));
adView.setStoreView(adView.findViewById(R.id.ad_store));
adView.setAdvertiserView(adView.findViewById(R.id.ad_advertiser));
}
}
}
surprised there is no answer here.
The approach I would use outside of the recyclerview adapter:
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS_TO_LOAD(Max 5 according to docs);
instead usual adLoader.loadAd
and then
builder.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
// OnUnifiedNativeAdLoadedListener implementation.
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
nativeAds.add(unifiedNativeAd);
}
});
where
private List<UnifiedNativeAd> nativeAds = new ArrayList<>();
which you pass to your recyclerview adapter and mix in your other items.
This will need some memory handling with destroy called before you request another list etc. but the idea is to preload a list of ads instead of loading them while scrolling

Insert a native ad in a recyclerview of viewpager fragment

I am trying to build my 1st app, and want to insert an admob native ad in a recyclerview.
I have created the viewpager from android studio's default tabbed activity, and have inserted a recyclerview, which is working fine.
Now, from AdMob Native Advanced Ads in an Android Feed I am trying to insert a native ad.
But, the codelab example uses Fragment Transaction. Do I must need to implement that?
It will be helpful for me, if I can implement the complete ad related part in the fragment only (except the initialisation).
Here is my current status of the fragment:
public class SunFragment extends Fragment {
public static final int NUMBER_OF_ADS = 1;
private AdLoader adLoader;
private List<Object> mRecyclerViewItems = new ArrayList<>();
private List<UnifiedNativeAd> mNativeAds = new ArrayList<>();
ArrayList<Object> sunsList;
Typeface sunfont;
Double Dlat;
Double Dlang;
//to be called by the MainActivity
public SunFragment() {
// Required empty public constructor
}
private static final String KEY_LOCATION_NAME = "location_name";
public String TAG = "SunFragment";
public String location;//="No location name found";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
location = savedInstanceState.getCharSequence(KEY_LOCATION_NAME).toString();
}
setRetainInstance(true);
}
public List<Object> getRecyclerViewItems() {
return mRecyclerViewItems;
}
private void loadNativeAds() {
AdLoader.Builder builder = new AdLoader.Builder(getContext(), getString(R.string.ad_unit_id));
adLoader = builder.forUnifiedNativeAd(
new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// A native ad loaded successfully, check if the ad loader has finished loading
// and if so, insert the ads into the list.
mNativeAds.add(unifiedNativeAd);
if (!adLoader.isLoading()) {
//insertAdsInMenuItems();
mRecyclerViewItems.add(3, mNativeAds);
}
}
}).withAdListener(
new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// A native ad failed to load, check if the ad loader has finished loading
// and if so, insert the ads into the list.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to"
+ " load another.");
if (!adLoader.isLoading()) {
//insertAdsInMenuItems();
}
}
}).build();
// Load the Native ads.
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
//onSaveInstanceState(new Bundle());
if (getArguments() != null) {
Dlat = getArguments().getDouble("loclat");
Dlang = getArguments().getDouble("loclang");
} else {
Dlat = 0.0;
Dlang = 0.0;
}
View rootView = inflater.inflate(R.layout.fragment_sun, container, false);
RecyclerView rv = rootView.findViewById(R.id.rv_recycler_view);
rv.setNestedScrollingEnabled(false);
rv.setHasFixedSize(true);
RecyclerView.LayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
// System.out.println("location " + location);
setRetainInstance(true);
RecyclerView.Adapter adapter = new SunAdapter(getContext(), sunsList);
rv.setAdapter(adapter);
return rootView;
}
#Override
public void onSaveInstanceState(Bundle locState) {
super.onSaveInstanceState(locState);
if (location != null) {
locState.putCharSequence(KEY_LOCATION_NAME, location);
}
}
}
and the adapter is:
public class SunAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context mContext;
private final ArrayList<Object> mSunsList;
private static final int MENU_ITEM_VIEW_TYPE = 0;
private static final int UNIFIED_NATIVE_AD_VIEW_TYPE = 1;
public SunAdapter(Context context, ArrayList<Object> sunsList) {
this.mContext = context;
this.mSunsList = sunsList;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView textViewId;
private TextView textViewSicon;
private TextView textViewStime;
private TextView textViewEicon;
private TextView textViewEtime;
private TextView ntextViewSicon;
private TextView ntextViewStime;
private TextView ntextViewEicon;
private TextView ntextViewEtime;
MyViewHolder(View itemView) {
super(itemView);
textViewId = itemView.findViewById(R.id.tv_city);
textViewSicon = itemView.findViewById(R.id.tv_MSicon);
textViewStime = itemView.findViewById(R.id.tv_MStime);
textViewEicon = itemView.findViewById(R.id.tv_MEicon);
textViewEtime = itemView.findViewById(R.id.tv_MEtime);
ntextViewSicon = itemView.findViewById(R.id.tv_NSicon);
ntextViewStime = itemView.findViewById(R.id.tv_NStime);
ntextViewEicon = itemView.findViewById(R.id.tv_NEicon);
ntextViewEtime = itemView.findViewById(R.id.tv_NEtime);
// mSportsImage = itemView.findViewById(R.id.sportsImage);
}
}
#Override
public int getItemCount() {
return mSunsList.size();
}
#Override
public int getItemViewType(int position) {
Object sunList = mSunsList.get(position);
if (sunList instanceof UnifiedNativeAd) {
return UNIFIED_NATIVE_AD_VIEW_TYPE;
}
return MENU_ITEM_VIEW_TYPE;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
switch (viewType) {
case UNIFIED_NATIVE_AD_VIEW_TYPE:
View unifiedNativeLayoutView = LayoutInflater.from(
viewGroup.getContext()).inflate(R.layout.ad_unified,
viewGroup, false);
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
case MENU_ITEM_VIEW_TYPE:
// Fall through.
default:
View menuItemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.card_item, viewGroup, false);
return new MyViewHolder(menuItemLayoutView);
}
}
// #RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case UNIFIED_NATIVE_AD_VIEW_TYPE:
UnifiedNativeAd nativeAd = (UnifiedNativeAd) mSunsList.get(position);
populateNativeAdView(nativeAd, ((UnifiedNativeAdViewHolder) holder).getAdView());
break;
case MENU_ITEM_VIEW_TYPE:
// fall through
default:
MyViewHolder myViewHolder = (MyViewHolder) holder;
SunSession sunSession = (SunSession) mSunsList.get(position);
myViewHolder.textViewId.setText(sunSession.getId());
myViewHolder.textViewSicon.setText(HtmlCompat.fromHtml(sunSession.getSicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.textViewStime.setText(sunSession.getStime());
myViewHolder.textViewEicon.setText(HtmlCompat.fromHtml(sunSession.getEicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.textViewEtime.setText(sunSession.getEtime());
myViewHolder.ntextViewSicon.setText(HtmlCompat.fromHtml(sunSession.getNSicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.ntextViewStime.setText(sunSession.getNStime());
myViewHolder.ntextViewEicon.setText(HtmlCompat.fromHtml(sunSession.getNEicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.ntextViewEtime.setText(sunSession.getNEtime());
}
}
private void populateNativeAdView(UnifiedNativeAd nativeAd,
UnifiedNativeAdView adView) {
// Some assets are guaranteed to be in every UnifiedNativeAd.
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
}
with this situation, the normal recyclerview is working, but no ad is inserted.
It will be really helpful if somebody shows me how to insert the ad, following the codelab, which probably means, how to implemeant this section in my fragment.

Ads in recyclerview

I have an app that stores some data in room database. At first, my adapter was like that:
public class ViewCourseAdapter extends ListAdapter<Course, ViewCourseAdapter.ViewCourseHolder> {
private int previousPosition = 0;
public ViewCourseAdapter() {
super(DIFF_CALLBACK);
}
private static final DiffUtil.ItemCallback<Course> DIFF_CALLBACK = new DiffUtil.ItemCallback<Course>() {
#Override
public boolean areItemsTheSame(#NonNull Course oldItem, #NonNull Course newItem) {
return oldItem.getId() == newItem.getId();
}
#Override
public boolean areContentsTheSame(#NonNull Course oldItem, #NonNull Course newItem) {
return oldItem.getfName().equals(newItem.getfName());
}
};
#NonNull
#Override
public ViewCourseHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_courses_item, parent, false);
return new ViewCourseHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull ViewCourseHolder holder, int position) {
Course currentCourse = getItem(position);
String fullName = currentCourse.getfName() + " " + currentCourse.getlName();
SpannableString SfullName = new SpannableString(fullName);
SfullName.setSpan(new UnderlineSpan(), 0, fullName.length(), 0);
holder.text_view_firstName_1.setText(SfullName);
if (position > previousPosition) {
AnimationUtil.animate(holder, true);
} else {
AnimationUtil.animate(holder, false);
}
previousPosition = position;
}
class ViewCourseHolder extends RecyclerView.ViewHolder {
private TextView text_view_firstName_1;
ViewCourseHolder(#NonNull View itemView) {
super(itemView);
text_view_firstName_1 = itemView.findViewById(R.id.text_view_firstName_1);
}
}
#Override
public int getItemCount() {
return super.getItemCount();
}
And everything was working perfect. Now I want to show ads inside recyclerview, so I changed my adapter:
public class ViewCourseAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int COURSE_VIEW_TYPE = 0;
private static final int AD_VIEW_TYPE = 1;
private List<Course> data;
private List<Object> ad;
private Context context;
private LayoutInflater layoutInflater;
private int previousPosition = 0;
public ViewCourseAdapter(Context context, List<Object> ad) {
this.data = new ArrayList<>();
this.context = context;
this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.ad = ad;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType ) {
case COURSE_VIEW_TYPE:
View courseView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_courses_item, parent, false);
return new ViewCourseViewHolder(courseView);
case AD_VIEW_TYPE:
default:
View adView = LayoutInflater.from(parent.getContext()).inflate(R.layout.native_ads, parent, false);
return new AdViewHolder(adView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case COURSE_VIEW_TYPE:
ViewCourseViewHolder holder1 = (ViewCourseViewHolder) holder;
Course currentCourse = (Course) data.get(position);
String fullName = currentCourse.getfName() + " " + currentCourse.getlName();
SpannableString SfullName = new SpannableString(fullName);
SfullName.setSpan(new UnderlineSpan(), 0, fullName.length(), 0);
holder1.text_view_firstName_1.setText(SfullName);
break;
case AD_VIEW_TYPE:
default:
AdViewHolder bannerHolder = (AdViewHolder) holder;
AdView adView = (AdView) ad.get(position);
ViewGroup adCardView = (ViewGroup) bannerHolder.itemView;
if (adCardView.getChildCount() > 0) {
adCardView.removeAllViews();
}
if (adView.getParent() != null) {
((ViewGroup) adView.getParent()).removeView(adView);
}
adCardView.addView(adView);
}
if (position > previousPosition) {
AnimationUtil.animate(holder, true);
} else {
AnimationUtil.animate(holder, false);
}
previousPosition = position;
}
class AdViewHolder extends RecyclerView.ViewHolder {
AdViewHolder(View view) {
super(view);
}
}
#Override
public int getItemViewType(int position) {
return (position % ViewCoursesActivity.ITEMS_PER_AD == 0) ? AD_VIEW_TYPE
: COURSE_VIEW_TYPE;
}
#Override
public int getItemCount() {
return data.size();
}
public void setData(List<Course> newData) {
if (data != null) {
CourseDiffCallback courseDiffCallback = new CourseDiffCallback(data, newData);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(courseDiffCallback);
data.clear();
data.addAll(newData);
diffResult.dispatchUpdatesTo(this);
} else {
data = newData;
}
}
public class ViewCourseViewHolder extends RecyclerView.ViewHolder {
private TextView text_view_firstName_1;
ViewCourseViewHolder(#NonNull View itemView) {
super(itemView);
text_view_firstName_1 = itemView.findViewById(R.id.text_view_firstName_1);
}
}
private class CourseDiffCallback extends DiffUtil.Callback {
private final List<Course> oldItem, newItem;
private CourseDiffCallback(List<Course> oldItem, List<Course> newItem) {
this.oldItem = oldItem;
this.newItem = newItem;
}
#Override
public int getOldListSize() {
return oldItem.size();
}
#Override
public int getNewListSize() {
return newItem.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldItem.get(oldItemPosition).getId() == newItem.get(newItemPosition).getId();
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldItem.get(oldItemPosition).getfName().equals(newItem.get(newItemPosition).getfName());
}
}
And my activity is:
public class ViewCoursesActivity extends AppCompatActivity {
private CourseViewModel courseViewModel;
// A banner ad is placed in every 8th position in the RecyclerView.
public static final int ITEMS_PER_AD = 8;
private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/6300978111";
// The RecyclerView that holds and displays banner ads and menu items.
private RecyclerView recyclerView;
// List of banner ads and MenuItems that populate the RecyclerView.
private List<Object> data = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_courses);
recyclerView = findViewById(R.id.recycler_view_3);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
addBannerAds();
loadBannerAds();
final ViewCourseAdapter adapter = new ViewCourseAdapter(this, data);
recyclerView.setAdapter(adapter);
courseViewModel = ViewModelProviders.of(this).get(CourseViewModel.class);
courseViewModel.setIdForCourse(0);
//courseViewModel.getCourseByStudentId().observe(this, adapter::submitList);
courseViewModel.getCourseByStudentId().observe(this, adapter::setData);
}
#Override
protected void onResume() {
for (Object item : data) {
if (item instanceof AdView) {
AdView adView = (AdView) item;
adView.resume();
}
}
super.onResume();
}
#Override
protected void onPause() {
for (Object item : data) {
if (item instanceof AdView) {
AdView adView = (AdView) item;
adView.pause();
}
}
super.onPause();
}
#Override
protected void onDestroy() {
for (Object item : data) {
if (item instanceof AdView) {
AdView adView = (AdView) item;
adView.destroy();
}
}
super.onDestroy();
}
/**
* Adds banner ads to the items list.
*/
private void addBannerAds() {
// Loop through the items array and place a new banner ad in every ith position in
// the items List.
for (int i = 0; i <= data.size(); i += ITEMS_PER_AD) {
final AdView adView = new AdView(ViewCoursesActivity.this);
adView.setAdSize(AdSize.SMART_BANNER);
adView.setAdUnitId(AD_UNIT_ID);
data.add(i, adView);
}
}
/**
* Sets up and loads the banner ads.
*/
private void loadBannerAds() {
// Load the first banner ad in the items list (subsequent ads will be loaded automatically
// in sequence).
loadBannerAd(0);
}
/**
* Loads the banner ads in the items list.
*/
private void loadBannerAd(final int index) {
if (index >= data.size()) {
return;
}
Object item = data.get(index);
if (!(item instanceof AdView)) {
throw new ClassCastException("Expected item at index " + index + " to be a banner ad"
+ " ad.");
}
final AdView adView = (AdView) item;
// Set an AdListener on the AdView to wait for the previous banner ad
// to finish loading before loading the next ad in the items list.
adView.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
// The previous banner ad loaded successfully, call this method again to
// load the next ad in the items list.
loadBannerAd(index + ITEMS_PER_AD);
}
#Override
public void onAdFailedToLoad(int errorCode) {
// The previous banner ad failed to load. Call this method again to load
// the next ad in the items list.
Log.e("ViewCoursesActivity", "The previous banner ad failed to load. Attempting to"
+ " load the next banner ad in the items list.");
loadBannerAd(index + ITEMS_PER_AD);
}
});
// Load the banner ad.
adView.loadAd(new AdRequest.Builder().build());
}
After that I have two problems:
1. At frist position it display an ad instead of first item from my database, and first item is nowhere. If I check my database first item is there, just not apear in recyclerview.
2. If I want to scroll items, the app crash, and the error is "java.lang.IndexOutOfBoundsException: Index: 8, Size: 1".
What am I doing wrong?
Please help me. Thank you!
Fundamentally, a RecyclerView is used to display a List to the user. Use this to guide your implementation.
Currently, you have two lists:
private List<Course> data;
private List<Object> ad;
You need to find a way to "collate" these down to a single list. Maybe something like this:
private static List<Object> collate(List<Course> data, List<Object> ads) {
List<Object> collated = new ArrayList<>();
while (data.size() > 0 || ads.size() > 0) {
for (int i = 0; i < ITEMS_PER_AD && data.size() > 0; ++i) {
collated.add(data.remove(0));
}
if (ads.size() > 0) {
collated.add(ads.remove(0));
}
}
return collated;
}
With that method defined, you can replace your existing constructor:
private List<Course> data;
private List<Object> ad;
// ...
public ViewCourseAdapter(Context context, List<Object> ad) {
this.data = new ArrayList<>();
this.ad = ad;
// ...
}
with this:
private List<Object> ad;
private List<Object> collated;
// ...
public ViewCourseAdapter(Context context, List<Object> ad) {
this.ad = ad;
this.collated = new ArrayList<>(ad);
// ...
}
And you can replace your existing setData() method:
public void setData(List<Course> newData) {
if (data != null) {
CourseDiffCallback courseDiffCallback = new CourseDiffCallback(data, newData);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(courseDiffCallback);
data.clear();
data.addAll(newData);
diffResult.dispatchUpdatesTo(this);
} else {
data = newData;
}
}
with this:
public void setData(List<Course> newData) {
if (data != null) {
List<Object> newCollated = collate(ad, newData);
// setup DiffUtil callback here...
this.collated = newCollated;
// dispatch DiffUtil result here...
}
}
Now you will have a single list that you can use in your adapter. Then you can change your adapter's methods to use that one list:
#Override
public int getItemCount() {
return collated.size();
}
#Override
public int getItemViewType(int position) {
return (collated.get(position) instanceof Course)
? COURSE_VIEW_TYPE
: AD_VIEW_TYPE;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == COURSE_VIEW_TYPE) {
bindCourseHolder((ViewCourseViewHolder) holder, position);
} else if (holder.getItemViewType() == AD_VIEW_TYPE) {
bindAdHolder((AdViewHolder) holder, position);
}
}
private void bindCourseHolder(ViewCourseViewHolder holder, int position) {
// ...
}
private void bindAdHolder(AdViewHolder holder, int position) {
// ...
}
All of these changes are based on the fundamental concept that you just have a single list, and that list holds (potentially) many different types of things.
Thank you #Ben P. for advice...I can't believe I didn't see this...so I modify collate() method like this:
while (data.size() > 0) {
collated.addAll(ad);
for (int i = 0; i < ITEMS_PER_AD && data.size() > 0; ++i) {
collated.add(data.remove(0));
}
}
ad.remove(0);
return collated;
It is there a better way to do this?

ADS in the RecyclerView are not displayed correctly

Friends, help me please. I'm making a RecyclerView with ads. The list is not displayed correctly. When embedded advertising, break sequence list. In the screenshot I give an example.
The list is not currently displayed correctly. Item 10 is not displayed:
I need Item 10 to be visible as in this screenshot:
My adapter code:
public class ScheduleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Card> scheduleList;
private static final int CONTENT = 0;
private static final int AD = 1;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textDate;
public TextView textSubject;
public Button share;
public MyViewHolder(View view) {
super(view);
textDate = view.findViewById(R.id.textDate);
textSubject = view.findViewById(R.id.textSubject);
share = view.findViewById(R.id.shareBtn);
Typeface custom_font = Typeface.createFromAsset(view.getContext().getAssets(), "Exo2Light.ttf");
textDate.setTypeface(custom_font);
textSubject.setTypeface(custom_font);
}
}
public static class ViewHolderAdMob extends RecyclerView.ViewHolder {
public AdView mAdView;
public ViewHolderAdMob(View view) {
super(view);
mAdView = view.findViewById(R.id.adView);
}
}
public ScheduleAdapter(List<Card> scheduleList) {
this.scheduleList = scheduleList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == CONTENT) {
View v = inflater.inflate(R.layout.recycler_item, parent, false);
viewHolder = new MyViewHolder(v);
} else {
View v = inflater.inflate(R.layout.recycler_item_admob, parent, false);
viewHolder = new ViewHolderAdMob(v);
}
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == CONTENT) {
MyViewHolder viewHolder = (MyViewHolder) holder;
Card card = scheduleList.get(position);
viewHolder.textDate.setText(card.getDateline());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
viewHolder.textSubject.setText(Html.fromHtml(card.getContentline(), Html.FROM_HTML_MODE_COMPACT));
else
viewHolder.textSubject.setText(Html.fromHtml(card.getContentline()));
((MyViewHolder) holder).share.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// handle your click here.
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_TEXT, "\uD83D\uDCC5 " + ((MyViewHolder) holder).textDate.getText().toString()+"\r\n"+((MyViewHolder) holder).textSubject.getText().toString());
v.getContext().startActivity(Intent.createChooser(sharingIntent,"Поділитися..."));
} });
} else {
AdRequest adRequest = new AdRequest.Builder()
//.addTestDevice("B86C95B89D21A5F8E2C22F0D94470A13")
.build();
((ViewHolderAdMob) holder).mAdView.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
((ViewHolderAdMob) holder).mAdView.setVisibility(View.VISIBLE);
}
#Override
public void onAdFailedToLoad(int errorCode) {
super.onAdFailedToLoad(errorCode);
((ViewHolderAdMob) holder).mAdView.setVisibility(View.GONE);
}
});
((ViewHolderAdMob) holder).mAdView.loadAd(adRequest);
}
}
#Override
public int getItemViewType(int position) {
if (position == 10) {
return AD;
}
return CONTENT;
}
#Override
public int getItemCount() {
return scheduleList.size();
}
}
Replace your code with
#Override
public int getItemCount() {
return scheduleList.size() + 1;
}
and use this function get Card object in onBindViewHolder
public Card getItem(int position) {
if(position > 10){
return scheduleList.get(position - 1)
}else{
return scheduleList.get(position)
}
}
By adding 1 to getItemCount() function, we are making adapter to draw one more line which represents ad.
And being sure we dont have IndexOutOfBoundsException for 13th row by decreasing position by minus one for the values which bigger than 10 in getItem(int position) function.

Admob banner ads making my recyclerview lag

I am showing banner ads within my android app. I followed official doc for implementing admob banner contentView ads and I successfully loaded ads but now my recyclerview starts lagging like hell. If i remove ads from my code scroll becomes smooth. Please help me with this problem.
Here's my fragment class
public class WallpaperFragment extends Fragment {
private RecyclerView recyclerView;
private DatabaseReference wallRef;
private String category;
private FirebaseAuth mAuth;
private final String CATEGORY = "Category";
private Context context;
private ArrayList<Object> modelList = new ArrayList<>();
private GridLayoutManager manager;
// The number of native ads to load and display.
public int NUMBER_OF_ADS = 5;
// List of native ads that have been successfully loaded.
private List<NativeAd> mNativeAds = new ArrayList<>();
private WallpaperAdapter adapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fg_wallpaper, container, false);
category = "Recent";
init(view);
Util.showDialog(context, "Loading wallpapers...");
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return (position % (SPACE_BETWEEN_ADS + 1) == SPACE_BETWEEN_ADS) ? 2 : 1;
}
});
setScrollListener();
initializeFirebaseDatabase();
return view;
}
private void init(View view) {
context = getContext();
MobileAds.initialize(context, getString(R.string.admob_app_id));
wallRef = FirebaseDatabase.getInstance().getReference().child(WALL).child(CATEGORY).child(category).getRef();
mAuth = FirebaseAuth.getInstance();
recyclerView = view.findViewById(R.id.recyclerView);
manager = new GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(manager);
recyclerView.addItemDecoration(new GridItemDecor(0));
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(null);
}
private void setScrollListener() {
recyclerView.addOnScrollListener(new HidingScrollListener() {
#Override
public void onHide() {
if (context instanceof ToolbarShowHideListener) {
((ToolbarShowHideListener) context).hideBottomNavigation();
}
}
#Override
public void onShow() {
if (context instanceof ToolbarShowHideListener) {
((ToolbarShowHideListener) context).showBottomNavigation();
}
}
});
}
private void initializeFirebaseDatabase() {
mNativeAds.clear();
wallRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
modelList.clear();
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
WallpaperModel model = childDataSnapshot.getValue(WallpaperModel.class);
modelList.add(model);
}
NUMBER_OF_ADS = modelList.size() / 2;
loadNativeAd();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void loadNativeAd() {
loadNativeAd(0);
}
private void insertAdsInMenuItems() {
if (mNativeAds.size() <= 0) {
return;
}
int offset = (modelList.size() / mNativeAds.size()) + 1;
int index = 2;
for (NativeAd ad : mNativeAds) {
modelList.add(index, ad);
index = index + offset;
}
if (adapter == null) {
adapter = new WallpaperAdapter(context, modelList, Objects.requireNonNull(mAuth.getCurrentUser()).getUid(), true, WALLPAPER_FRAGMENT);
recyclerView.setAdapter(adapter);
} else {
adapter.updateList(modelList);
}
}
private void loadNativeAd(final int adLoadCount) {
if (adLoadCount >= NUMBER_OF_ADS) {
insertAdsInMenuItems();
return;
}
AdLoader.Builder builder = new AdLoader.Builder(context, /*getString(R.string.ad_unit_id)*/"ca-app-pub-3940256099942544/2247696110");
AdLoader adLoader = builder.forContentAd(new NativeContentAd.OnContentAdLoadedListener() {
#Override
public void onContentAdLoaded(NativeContentAd ad) {
// A content ad loaded successfully, call this method again to
// load the next ad in the items list.
mNativeAds.add(ad);
loadNativeAd(adLoadCount + 1);
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// A native ad failed to load. Call this method again to load
// the next ad in the items list.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to" +
" load another.");
loadNativeAd(adLoadCount + 1);
}
}).build();
// Load the Native Express ad.
adLoader.loadAd(new AdRequest.Builder().addTestDevice("9F50A23B86C21B90330202FAECE3C331").build());
}
}
and here's my adapter class,
public class WallpaperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private int height, fragment_id;
private String uId;
private Animation fadeout, fadein;
private DatabaseReference favCheckRef;
private final String CATEGORY = "Category";
private ArrayList<Object> modelList;
private boolean showLikeBtn;
public WallpaperAdapter(Context context, ArrayList<Object> modelList, String uId, boolean showLikeBtn, int fragment_id) {
this.context = context;
this.modelList = modelList;
this.uId = uId;
this.showLikeBtn = showLikeBtn;
height = context.getResources().getDisplayMetrics().heightPixels;
fadeout = AnimationUtils.loadAnimation(context, R.anim.anim_fade_out);
fadein = AnimationUtils.loadAnimation(context, R.anim.anim_fade_in);
favCheckRef = FirebaseDatabase.getInstance().getReference().child(WALL).child(USER)
.child(uId).child(FAVOURITES).getRef();
this.fragment_id = fragment_id;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case NATIVE_CONTENT_AD_VIEW_TYPE:
View nativeContentLayoutView = LayoutInflater.from(
parent.getContext()).inflate(R.layout.ad_content,
parent, false);
return new NativeContentAdViewHolder(nativeContentLayoutView);
case MENU_ITEM_VIEW_TYPE:
// Fall through.
default:
View dataView = LayoutInflater.from(context).inflate(R.layout.single_wallpaper_unit, parent, false);
return new ViewHolder(dataView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
Util.dismissDialog();
switch (viewType) {
case NATIVE_CONTENT_AD_VIEW_TYPE:
NativeContentAd contentAd = (NativeContentAd) modelList.get(position);
populateAdView(contentAd, (NativeContentAdView) holder.itemView);
break;
case MENU_ITEM_VIEW_TYPE:
// fall through
default:
final ViewHolder wallHolder = (ViewHolder) holder;
WallpaperModel model = (WallpaperModel) modelList.get(position);
wallHolder.wallpaper.getLayoutParams().height = (int) (height / 2.5);
wallHolder.name.setText(model.getName());
favCheck(wallHolder, model);
Glide.with(wallHolder.wallpaper.getContext())
.load(model.getThumbnail())
.into(wallHolder.wallpaper);
break;
}
}
#Override
public int getItemViewType(int position) {
Object recyclerViewItem = modelList.get(position);
if (recyclerViewItem instanceof NativeContentAd) {
return NATIVE_CONTENT_AD_VIEW_TYPE;
}
return MENU_ITEM_VIEW_TYPE;
}
#Override
public int getItemCount() {
return modelList.size();
}
private void populateAdView(NativeContentAd ad,NativeContentAdView adView){
((TextView) adView.getHeadlineView()).setText(ad.getHeadline());
List<NativeAd.Image> images = ad.getImages();
if (images.size() > 0) {
((ImageView) adView.getImageView()).setImageDrawable(images.get(0).getDrawable());
}
adView.setNativeAd(ad);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
ImageView wallpaper, favouriteIcon;
private ViewHolder(View itemView) {
super(itemView);
wallpaper = itemView.findViewById(R.id.wallpaper);
name = itemView.findViewById(R.id.name);
favouriteIcon = itemView.findViewById(R.id.favouriteIcon);
}
}
public class NativeContentAdViewHolder extends RecyclerView.ViewHolder {
NativeContentAdViewHolder(View view) {
super(view);
NativeContentAdView adView = (NativeContentAdView) view;
adView.setHeadlineView(adView.findViewById(R.id.contentad_headline));
adView.setImageView(adView.findViewById(R.id.contentad_image));
}
}
}
You are loading native express, not banner.
The problem is the ads have images, just like a normal viewholder, you have to handel the caching of the images, I see you already use glide...
Also, it's not a good idea showing your ad ID.
Last thing, NONE of this matters because native express ads are deprecated and will anyway not work.
Another option is to use Native Ads Advance, but unless you have a few million downloads you will not be able to use it - look here:
Note: Native Ads Advanced is currently released to a limited set of publishers. If you're interested in participating, reach out to your account manager to discuss the possibility.
What I would suggest is using some ad provider like Appodeal which supports native ads.

Categories

Resources