1

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

1 Answer 1

2

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);
Sign up to request clarification or add additional context in comments.

3 Comments

i'm not sure what to pass in for the context argument, i'm getting "NoClassDefFoundError" when i use Picasso: protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView iv = (ImageView) findViewById(R.id.imageView1); Picasso.with(getApplicationContext()).load(R.drawable.appertizers_curly_twister_fries).into(iv); } what should i put for the context?
it does not help i'm afraid, getActivity() method does not exist in my package
if you are using Picasso in an activity use this, if you are using it in a fragment use getActivity(). If you are using it in an adapter you should pass the context in the constructor

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.