ListView导致OutOfMemory错误

时间:2014-08-24 03:20:02

标签: android listview baseadapter android-viewholder

所以我没有给出这个错误消息的正确理由。我不确定为什么会发生这种情况,但我的猜测是,它与大约有50个质量好的抽屉有关。滚动速度非常快,应用程序崩溃。我觉得好像我正在缓解ListView的最常见问题并且崩溃,例如使用View Holders以及仅启动inflater一次。

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

这是代码

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;
  }
}

4 个答案:

答案 0 :(得分:2)

我真的不确定您要对适配器做什么,但是您有逻辑错误/重言式。

您将rowView指定为空,然后检查它是否为null。它将始终为null,您永远不会最终使用ViewHolder

答案 1 :(得分:0)

您需要使用LRUCache

缓存图片

这是一个众所周知的问题,因此有很好的解决方法。

Android-Universal-Image-Loader

可接受的URI示例:

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);

答案 2 :(得分:0)

除了@PeekaySwitch突出显示的错误之外,我只想强调一下,你真的不需要列表中的高清图片。当今设备的普通高清屏幕具有 1920x1080 分辨率。这样就可以在一个屏幕上显示最高质量。但考虑到屏幕的某些部分被其他图形组件占用并且您有一个列表,因此您希望每个屏幕显示少量图像,这意味着每个图像的屏幕部分会大幅减少。您加载了一堆 HD 图像,但在屏幕上显示的很可能是&lt;其大小的1/10 意味着不必要的内存使用。因此我建议在处理图像时重新考虑这种方法。您可能想要创建一些缩略图或某些缩略图,以便按列表的每个项目显示。例如,用户点击它时的整个图像。 此外,您可以考虑应用一些缓存机制,如Android中可用的LRU。

答案 3 :(得分:0)

Drawables在资源中的压缩程度无关紧要,重要的是它们的未压缩程度。如上所示,您的图片尺寸为500x726。对于RGB,每个图像的未压缩大约为1MB。

一些建议:

尽可能缩放图像。我怀疑你是否使用Photoshop,Gimp,Paint.Net或MSPaint将图像缩放到250x363,你会没事的。或者只看一下ScalableDrawable类。

避免在屏幕上保留对Drawable的任何引用。

在我的ListView中,我使用URLImageViewHelper来管理引用和LRU缓存。