0

So I am not really given a reason to the right of this error message. I am not exactly sure why this is happening but my guess though is that it has to do with the fact that there are around ~50 good quality drawables. Upon scrolling really fast, the app crashes. I feel as if I am mitigating most common issues with ListView and crashing such as using View Holders as well as only initiating the inflater once.

Process: com.example.michael.myandroidappactivity, PID: 20103
java.lang.OutOfMemoryError
        at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)

Here is the code

public class ImageAdapter extends BaseAdapter
{
private Context context;
private ArrayList<Integer> imageIds;
private static LayoutInflater inflater;

public ImageAdapter(Context _context, ArrayList<Integer> _imageIds)
{
    context = _context;
    imageIds = _imageIds;
}

@Override
public int getCount()
{
    return imageIds.size();
}

@Override
public Object getItem(int position)
{
    return null;
}

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

static class ViewHolder{
    ImageView img;
}

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

    ViewHolder holder = null;
    View rowView = null;

    if(rowView==null) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        rowView = inflater.inflate(R.layout.listview_layout, parent, false);
        holder = new ViewHolder();
        holder.img = (ImageView) rowView.findViewById(R.id.flag);
        rowView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) rowView.getTag();
    }
    holder.img.setImageResource(imageIds.get(position));
    return rowView;
  }
}
Michael
  • 83
  • 9
  • What size are your images as stored in the resources? What size are they actually rendered on screen (as specified by your layout)? Even if you are showing the images scaled down, Android is still keeping the full sized image in memory. Consider scaling down the image to be closer to the render size either at runtime or within the resource itself. – selbie Aug 24 '14 at 05:34
  • Selbie- ~42kb up to 256kB and 500x726. – Michael Aug 24 '14 at 19:23
  • It doesn't matter how compressed the Drawables are in the resources, what counts is how big they are uncompressed. Each 500x726 image is about 1MB. You start to put 50 on the screen, you got 50MB allocated ... I'll post the rest as an answer. – selbie Aug 24 '14 at 19:56

4 Answers4

2

I'm really not sure what you're trying to do with your Adapter, but you have a logical error / tautology.

You assign rowView to null and check if it's null right after. It'll will always be null and you'll never end up using your ViewHolder.

Alexandre
  • 4,382
  • 2
  • 23
  • 33
0

You need to cache the images using LRUCache

this is a well known problem, and thus has good practice to solve the problem.

Android-Universal-Image-Loader

Acceptable URIs example:

String imageUri = "http://url/image.png"; // from Web
String imageUri = "file:///mnt/sdcard/image.png"; // from SD card
String imageUri = "content://media/external/audio/albumart/13"; // from content provider
String imageUri = "assets://image.png"; // from assets
String imageUri = "drawable://" + R.drawable.image; // from drawables (only images, non-9patch)

// Load image, decode it to Bitmap and display Bitmap in ImageView (or any other view 
// which implements ImageAware interface)

imageLoader.displayImage(imageUri, imageView);
Anderson K
  • 5,445
  • 5
  • 35
  • 50
0

Apart from the errors that @PeekaySwitch highlighted I just want to emphasize that you dont really need HD pictures in a list. The common HD screen of today's devices are of 1920x1080 resolution. So thats the maximum quality you can display in one single screen. But considering the fact that some part of the screen is occupied by other graphic components and you have a list so you want to display few images per screen, it means that your screen section per image is drastically reduced. You load a bunch of HD images but on the screen it is displayed most probably < 1/10 of its size which means unnecessary usage of memory. Therefore i would suggest to reconsider the approach when dealing with images. You may want to create some thumbnails or sth, to be displayed per each item of the list. And the whole image when the user clicks on it for example. Moreover you can consider applying some cache mechanisms such as LRU available in android.

eldjon
  • 2,800
  • 2
  • 20
  • 23
0

It doesn't matter how compressed the Drawables are in the resources, what counts is how big they are uncompressed. As you indicate above, your images have dimensions of 500x726. For RGB, that's about 1MB uncompressed for each image.

Some suggestions:

Scale your images back if at all possible. I suspect if you used Photoshop, Gimp, Paint.Net, or MSPaint to scale the images to 250x363, you'll be fine. Or just look at the ScalableDrawable class.

Avoid keeping any reference to a Drawable not on the screen.

In my ListView, I made use of URLImageViewHelper to manage the references and LRU cache.

selbie
  • 100,020
  • 15
  • 103
  • 173