Reputation: 95
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;
}
}
Upvotes: 1
Views: 435
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