0

I'm using recyclerview to list around 120 layouts that include 1 Imagebutton,1 Textview and 1 Button. The initial memory usage when i first launch the activity that has the recyclerview inside it is around 50mb. But as i scroll it increases dramatically and reaches 130-150mb as i get to the end of the list. I'm using a GridLayoutManager as my LayoutManager with span count of 3.

My images are fairly small ( only 200x200 , size of all 120 images is 612 KB)

What is causing this increase of memory usage ? and how can i solve this problem. I'm getting alot of OutOfMemory crash reports and mainly they happen in android 6. Thanks for yout time.

*I have tried using a third party library like Picasso instead of setting the background recourse. *I have tried decoding the images with bitmap factory

Initializing my recyclerview in Emotes activity :

recyclerView = findViewById(R.id.recyclerview);
            adapter = new Adapter(arr, this);
            adapter.setHasStableIds(true);
            recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
            recyclerView.setHasFixedSize(true);
            recyclerView.setItemViewCacheSize(20);


            recyclerView.setAdapter(adapter);

My Adapter:

public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {

    private CommonMethods commonMethodsInterface;
    private ArrayList<Emote> emoteArray ;
    private ArrayList<Emote> emoteArrayFull;



    public Adapter(ArrayList<Emote> emoteArray,CommonMethods commonMethodsInterface) {
        this.emoteArray = new ArrayList<>(emoteArray);
        this.emoteArrayFull = new ArrayList<>(emoteArray);

        this.commonMethodsInterface = commonMethodsInterface;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_listitem,viewGroup,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int i) {

        viewHolder.emoteButton.setBackgroundResource(emoteArray.get(i).getIconPath());
        viewHolder.text.setText(emoteArray.get(i).getName().toUpperCase());

        viewHolder.emoteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DatabaseConstants.INTERSTITIAL_AD_COUNTER++;
                commonMethodsInterface.ShowInterstitialAd();
                commonMethodsInterface.playEmoteSound(emoteArray.get(i));



         }
        });
        viewHolder.optionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DatabaseConstants.INTERSTITIAL_AD_COUNTER++;
                commonMethodsInterface.ShowInterstitialAd();
                commonMethodsInterface.ShowDialog(emoteArray.get(i));
            }
        });
    }


    @Override
    public int getItemCount() {
        return emoteArray.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }
 public static class ViewHolder extends RecyclerView.ViewHolder{

        ImageButton emoteButton;
        Button optionButton;
        TextView text;



        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            emoteButton = itemView.findViewById(R.id.tempimagebutton);
            optionButton = itemView.findViewById(R.id.tempbutton);
            text = itemView.findViewById(R.id.temptext);


        }
    }
}

Stacktrace

java.lang.OutOfMemoryError: 
  at dalvik.system.VMRuntime.newNonMovableArray (Native Method)
  at android.graphics.BitmapFactory.nativeDecodeAsset (Native Method)
  at android.graphics.BitmapFactory.decodeStream (BitmapFactory.java:709)
  at android.graphics.BitmapFactory.decodeResourceStream (BitmapFactory.java:530)
  at android.graphics.drawable.Drawable.createFromResourceStream (Drawable.java:1089)
  at android.content.res.Resources.loadDrawableForCookie (Resources.java:2963)
  at android.content.res.Resources.loadDrawable (Resources.java:2848)
  at android.content.res.HwResources.loadDrawable (HwResources.java:712)
  at android.content.res.Resources.getDrawable (Resources.java:970)
  at android.content.Context.getDrawable (Context.java:463)
  at android.view.View.setBackgroundResource (View.java:17562)
  at android.support.v7.widget.AppCompatImageButton.setBackgroundResource (AppCompatImageButton.java:114)
  at com.nullbytesoftware.example.Adapter.onBindViewHolder (Adapter.java:42)
 **at com.nullbytesoftware.example.Adapter.onBindViewHolder (Adapter.java:18)
  at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder (RecyclerView.java:6781)**
  at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder (RecyclerView.java:6823)
  at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline (RecyclerView.java:5752)
  at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java:6019)
  at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline (GapWorker.java:286)
  at android.support.v7.widget.GapWorker.flushTaskWithDeadline (GapWorker.java:343)
  at android.support.v7.widget.GapWorker.flushTasksWithDeadline (GapWorker.java:359)
  at android.support.v7.widget.GapWorker.prefetch (GapWorker.java:366)
  at android.support.v7.widget.GapWorker.run (GapWorker.java:397)
  at android.os.Handler.handleCallback (Handler.java:819)
  at android.os.Handler.dispatchMessage (Handler.java:104)
  at android.os.Looper.loop (Looper.java:210)
  at android.app.ActivityThread.main (ActivityThread.java:5982)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:852)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:742)
ibrahim
  • 573
  • 1
  • 6
  • 20
  • Check this out : https://stackoverflow.com/questions/29861929/android-java-lang-outofmemoryerror – Surabhi Choudhary Jun 30 '19 at 09:17
  • [https://stackoverflow.com/questions/41843758/how-to-clear-recyclerview-adapter-data/41843923] and [https://stackoverflow.com/questions/29861929/android-java-lang-outofmemoryerror/29863404#29863404] could help. – Seif Mostafa Jun 30 '19 at 10:50

2 Answers2

1

I don't know if it is a weird bug or if i did something wrong when implementing the Recyclerview but setting viewHolder.setIsRecyclable(false); made my RecyclerView start recycling elements and solved my memory problem.Still so curious to know the reason behind this opposite behavior.

ibrahim
  • 573
  • 1
  • 6
  • 20
0

There are some points to take care:

  1. No need to make viewHolder class as static.
  2. Don't add "View.OnClickListener" in "onBindViewHolder". You can use it in viewHolder class. like this
public class ViewHolder extends RecyclerView.ViewHolder{

        ImageButton emoteButton;
        Button optionButton;
        TextView text;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            emoteButton = itemView.findViewById(R.id.tempimagebutton);
            optionButton = itemView.findViewById(R.id.tempbutton);
            text = itemView.findViewById(R.id.temptext);

            emoteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DatabaseConstants.INTERSTITIAL_AD_COUNTER++;
                commonMethodsInterface.ShowInterstitialAd();
                commonMethodsInterface.playEmoteSound(
                    emoteArray.get(getAdapterPosition()));
         }
        });
        optionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DatabaseConstants.INTERSTITIAL_AD_COUNTER++;
                commonMethodsInterface.ShowInterstitialAd();              
                commonMethodsInterface.ShowDialog(
                   emoteArray.get(getAdapterPosition()));
            }
        });
        }
    }