1
votes

Update
I identified my problem. I am trying to handle the large list of images (770 images in the .webp format total size of images is 10mb) with RecyclerView and it is showing out of memory error.
How to solve this problem?
I am using picasso for loading images


Throwing OutOfMemoryError "Failed to allocate a 810076 byte allocation with 107504 free bytes and 104KB until OOM"

Old
There is no problem if the list size is less than 100, How to load 700 item using recycler view . Each item contains image in webp formant
I am trying this code and it is throwing out of memory error and crash the app . How to solve this error?
(It contain 700 iamges and all in webp format and this code inside recyclerview with grid layout)

 InputStream ins = null;

                try {
                    ins = mContext.getAssets().open(mData.get(position).getImagename()+".webp");
                    Bitmap bitmap = BitmapFactory.decodeStream(ins);
                    holder.image.setImageBitmap(bitmap);
                } catch (final IOException e) {
                    e.printStackTrace();
                } finally {
                    if (ins != null)
                        try {
                            ins.close();
                        } catch (IOException e) { }
                }

java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:805) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:845) at tropicalfishhandbook.midhilaj.com.v2.a.a.a(Unknown Source) at tropicalfishhandbook.midhilaj.com.v2.a.a.onBindViewHolder(Unknown Source) at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(Unknown Source) at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(Unknown Source) at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(Unknown Source) at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(Unknown Source) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(Unknown Source) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(Unknown Source) at android.support.v7.widget.LinearLayoutManager$LayoutState.next(Unknown Source) at android.support.v7.widget.GridLayoutManager.layoutChunk(Unknown Source) at android.support.v7.widget.LinearLayoutManager.fill(Unknown Source) at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(Unknown Source) at android.support.v7.widget.GridLayoutManager.onLayoutChildren(Unknown Source) at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(Unknown Source) at android.support.v7.widget.RecyclerView.onMeasure(Unknown Source) at android.view.View.measure(View.java:16749) at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719) at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455) at android.view.View.measure(View.java:16749) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5295) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1413) at android.widget.LinearLayout.measureVertical(LinearLayout.java:696) at android.widget.LinearLayout.onMeasure(LinearLayout.java:589) at android.view.View.measure(View.java:16749) at android.widget.ScrollView.measureChildWithMargins(ScrollView.java:1235) at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) at android.widget.ScrollView.onMeasure(ScrollView.java:327) at android.view.View.measure(View.java:16749) at android.support.constraint.ConstraintLayout.a(Unknown Source) at android.support.constraint.ConstraintLayout.onMeasure(Unknown Source) at android.view.View.measure(View.java:16749) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5295) at android.support.design.widget.CoordinatorLayout.a(Unknown Source) at android.support.design.widget.h.a(Unknown Source) at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.a(Unknown Source) at android.support.design.widget.CoordinatorLayout.onMeasure(Unknown Source) at android.view.View.measure(View.java:16749) at android.support.v4.widget.DrawerLayout.onMeasure(Unknown Source) at android.view.View.measure(View.java:16749) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5295) at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) at android.support.v7.widget.ContentFrameLayout.onMeasure(Unknown Source) at android.view.View.measure(View.java:16749) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5295) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1413) at android.widget.LinearLayout.measureVertical(LinearLayout.java:696) at android.widget.LinearLayout.onMeasure(LinearLayout.java:589) at android.view.View.measure(View.java:16749) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5295) at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) at android.view.View.measure(View.java:16749) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5295) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1413) at android.widget.LinearLayout.measureVertical(Lin

my manifest file

<application
        android:name=".App"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:supportsRtl="true"
        tools:replace="android:allowBackup"
        android:theme="@style/AppTheme">

Update I replaced with Picasso and it is working in the smartphone with 2gb ram and it is crashing in the smartphone with 500mb and it also crash sometime in 1gb ram smartphone
after adding picasso now images take 5sec to load

updated new code but problem not solved


This is the code I am using to load

try {
                       List<Millafish_profile> list = mDatabaseManager.getAll();
                       for (int i = 0; i < list.size(); i++) {
                           final int finalI = i;//"@drawable/" +
                           String uri = list.get(i).getPic().replace("’", "_").replace(".jpg", "").replace(".png", "").replace("-", "_");  // where myresource (without the extension) is the file
                           // Log.i("uri_"+i,uri+"");
                           Millafish_profile millafish_profile = list.get(i);//mDatabaseManager.getprofile(mDatabaseManager.getallfishname().get(finalI));
                           millafish_profile.setImageuri(uri.toLowerCase());
                           millafish_profileList.add(millafish_profile);
                           //if(i==20)break;

                           {
                               //adapter.notifyItemChanged(i);
                               //(millafish_profileList.size());
                           }

                       }
                       adapter.notifyDataSetChanged();
                       millafish_profileList_org = new ArrayList<>();
                       millafish_profileList_org.addAll(millafish_profileList);

                   }catch (Exception e){
                       Log.e("homepage",e.getMessage()+"");
                   }
2
did u tried to compress bitmapGautam Surani
no, I don't try to compressMidhilaj
the code is shared with questionMidhilaj
so tried to compress see my ansGautam Surani
Definitely it will crash and will have memory issue as images are too much. Better to use ListView or RecyclerView to load images one by one. By using this only rendered images will load in memory instead of all the images at once.Vikasdeep Singh

2 Answers

0
votes

Remove Picasso and use Glide

Glide.with(mContext).load(Uri.parse("file:///android_asset/"+mData.get(position).getImageuri()+".webp"))
                                .thumbnail(0.5f)

                                .into(holder.image);
0
votes

Add dependency

implementation 'com.squareup.picasso:picasso:2.71828'

RESOURCE LOADING

Picasso.get().load(R.drawable.landing_screen).into(imageView1);
Picasso.get().load("file:///android_asset/DvpvklR.png").into(imageView2);
Picasso.get().load(new File(...)).into(imageView3);

In your case

final String imagePath = "file:///android_asset/" + mData.get(position).getImagename()+".webp";

Picasso.get().load(imagePath).into(holder.image);

Update

Picasso.get()
.load(imagePath)
.centerCrop()
.fit()
// .resize(100, 100)  // Check if resize can help without fit/centerCrop
.memoryPolicy(MemoryPolicy.NO_CACHE)
.into(holder.image);

Update 2

Implement RecyclerView adapter.

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
      private final List<Millafish_profile> dataSet;

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView image;
        public ViewHolder(View v) {
            super(v);
            image = v.findViewById(R.id.image_view);
        }
    }

  public MyAdapter(){
    this.dataSet = mDatabaseManager.getAll();
  }
  // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View myView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.my_view_that_contains_imageview, parent, false);
        ...
        ViewHolder vh = new ViewHolder(myView);
        return vh;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        final String imagePath = "file:///android_asset/" + dataSet.get(position).getImagename()+".webp";
        Picasso.get().load(imagePath).into(holder.image);
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return dataSet.size();
    }
  • RecyclerView will handle load more images with user scrolling.

onBindViewHolder is called when need to displayed items on the screen then your display logic will be there and Just load on item based to position.