Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recyclerview lag on scroll due to Admob ads

I want to load ads in RecyclerView ads are loaded successfully but it is casuing so much lag while scrolling

Following is code I have written in OnBindViewHolder method of Adapter

How to fix this lag?

((DealHolder) holder).adcardView.post(new Runnable() {
                @Override
                public void run() {
                    final NativeExpressAdView adView = new NativeExpressAdView(((DealHolder) holder).itemView.getContext());
                    final int adWidth = ((DealHolder) holder).adcardView.getWidth() - ((DealHolder) holder).adcardView.getPaddingLeft()
                            - ((DealHolder) holder).adcardView.getPaddingRight();
                    final int adHeight = ((DealHolder) holder).adcardView.getHeight() - ((DealHolder) holder).adcardView.getPaddingBottom()
                            - ((DealHolder) holder).adcardView.getPaddingTop();
                    final float scale = ((DealHolder) holder).adcardView.getResources().getDisplayMetrics().density;
                    AdSize adSize = new AdSize((int) (adWidth / scale), (int) (adHeight / scale));
                    adView.setAdSize(adSize);
                    adView.setAdUnitId(((DealHolder) holder).adcardView.getContext().getString(R.string.test_adunit_id));
                    AdRequest request = new AdRequest.Builder().addTestDevice("jjhjhbjhjhjhjhjhjhjh").build();
                    adView.loadAd(request);
                    adView.setAdListener(new AdListener() {
                        @Override
                        public void onAdLoaded() {
                            super.onAdLoaded();
                        }

                        @Override
                        public void onAdFailedToLoad(int i) {
                            super.onAdFailedToLoad(i);
                        }
                    });
                    ((DealHolder) holder).adcardView.removeAllViews();
                    ((DealHolder) holder).adcardView.addView(adView);
                }
            });
like image 694
amodkanthe Avatar asked Jul 04 '17 19:07

amodkanthe


2 Answers

Improvements :

  1. Do not try to load your Adview when the user is trying to scroll. To do that make your adapter recylerView scroll aware and then check whether the scroll_state==RecylerView.Scroll_IDLE, then only load your AdView.

  2. If all your adViews have same width and height do not calculate it every time user scrolls, cache it in a variable.

  3. Instead of dynamically adding and removing your NativeExpressAdView, use a XML version for it in your item_view. You can hide and show based on conditions. Set all the possible required attributes in XML view.

like image 75
krishan Avatar answered Oct 21 '22 01:10

krishan


Creating a new AdView for each view holder would be quite Resource hungry.

Instead of creating new adview on each view holder inflate adview after a certain interval like e.g after every 5 or 10 items.

  • Create two different layouts to use in adapter one with ads and another without ads.

  • Override getItemViewType() method

public int getItemViewType(int position) { if (position % 10 == 0){ // Ad after every 10 items return 0; //use integer constant to identify view type is Adview. } return super.getItemViewType(position); }

  • in OnCreateViewHolder() method

    @Override public ViewHolderClass onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == 0){ // Constant for Adview View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_row_with_ads, parent,false); return new ViewHolderClass(view, viewType); } View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_row, parent,false); return new ViewHolderClass(view); }

  • In your ViewholderClass create a second Constructor with parameters View and int

    public class ViewHolderClass extends RecyclerView.ViewHolder{ ... public ViewHolderClass(View view){ ... } public ViewHolderClass(View view, int viewType){ ... // Initialize your adview here }

  • For your layouts. If your adapter_row.xml is like this :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp" >

    <android.support.v7.widget.CardView
        android:id="@+id/base"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        // your main content
    </android.support.v7.widget.CardView>
</RelativeLayout>
  • Then create another layout file for adapter adapter_row_with_ads.xml with these changes.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp" >

    <android.support.v7.widget.CardView
        android:id="@+id/base"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        // your main content

    </android.support.v7.widget.CardView>

      <!--This is where you'll add your AdView-->
      <com.google.android.gms.ads.AdView
          android:id="@+id/adView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_below="@id/base"/>

</RelativeLayout>

This approach will reduce battery drainage and resource consumption and your app will be smoother

like image 1
Mohammed Junaid Avatar answered Oct 21 '22 03:10

Mohammed Junaid