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

Viewed 1118

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));
        }
    }
}
1 Answers

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

Related