johnny manolly
johnny manolly

Reputation: 95

Android out of memory error when using ListView and Bitmap

I have used ViewHolder + Bitmap decodes/compress and imageCache in my ListView so i can no longer have out of memory error but unfortunately i'm still getting it, it happens mostly when i'm back to my ListView Activity from another Activity, or when i go from my current ListView Activity to another ListView Activity. Can anyone please tell me if i'm missing something? here's my code:

private class MyAdapter extends ArrayAdapter<String> {

     LruCache<Integer, Bitmap> imageCache;

        public MyAdapter(Context context, int resource, int textViewResourceId, String[] strings) {
            super(context, resource, textViewResourceId, strings);

            final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
            final int casheSize = maxMemory / 8;
            imageCache = new LruCache<>(casheSize);
         }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            ViewHolderItem viewHolder;
            String[] names = getResources().getStringArray(R.array.grilled_fresh_beef_names);
            String[] prices = getResources().getStringArray(R.array.grilled_fresh_beef_prices);
            String[] ingredients = getResources().getStringArray(R.array.grilled_fresh_beef_ingredients);

            if(convertView==null) {
                LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.categories_item, parent, false);


                viewHolder = new ViewHolderItem();

                viewHolder.item_name = (TextView) convertView.findViewById(R.id.items_name);
                viewHolder.item_price = (TextView) convertView.findViewById(R.id.item_price);
                viewHolder.item_ingredient = (TextView) convertView.findViewById(R.id.ingredients);
                viewHolder.imageView = (ImageView) convertView.findViewById(R.id.item_image);
                viewHolder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

                convertView.setTag(viewHolder);

            } else {
                viewHolder = (ViewHolderItem) convertView.getTag();
            }


         viewHolder.item_name.setText(names[position]);
            viewHolder.item_price.setText(prices[position]);
            viewHolder.item_ingredient.setText(ingredients[position]);



            Bitmap bitmap = imageCache.get(position);
            if (bitmap == null) {
                bitmap = BitmapFactory.decodeResource(getResources(), beef_burger[position]);
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);


                imageCache.put(position, bitmap);
            }

            viewHolder.imageView.setImageBitmap(bitmap);

            return convertView;
        }


     }

Logcat

Upvotes: 1

Views: 435

Answers (1)

Eoin
Eoin

Reputation: 4066

The problem using the lru cache the way you do is you are keep a reference to all the bitmaps you create even the one ones that are not on screen. Android is not able to garbage collect these and resuse them because of this reference to the lru cache.

As the other answer stated its better to use a library to take care of the caching for you. I would recommend Picasso or Glide.

I personally use glide. It seems to load images that bit faster and its perfect for loading images in a listview.

Its as simple as

Glide.with(context)
    .load(***image file/path/bitmap***)
    .into(viewHolder.imageView);

Upvotes: 2

Related Questions