【问题标题】:Android Bitmap OutOfMemoryError in ListViewListView中的Android位图OutOfMemoryError
【发布时间】:2016-03-27 19:40:55
【问题描述】:

我正在尝试使用 ListView 制作一个每行都有一个图像的 android 应用程序。我想用 BLOB 数据类型将所有图像存储在 SQLite 数据库中,然后用这些图像填​​充 ListView,但是每当我在列表中有超过 2 个 jpeg 图像时,我就会得到 OutOfMemoryError。我已经尝试了互联网上的许多技术来减少内存的使用,但仍然无法解决这个问题。我在 android 文档中发现了 options.inJustDecodeBounds 和 options.inSampleSize 的使用,但仍然得到相同的异常。您可以在下面找到我的位图到字节数组和字节数组到位图转换的代码。

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;


public class ListItem {

private int id;
private byte [] img;
private String title;
private String description;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public byte[] getImg() {
    return img;
}

public void setImg(byte[] img) {
    this.img = img;
}

public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public static byte[] convertBitmapToBytes(Bitmap bmp){
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    byte[] byteArray = stream.toByteArray();
    return byteArray;
}

public static Bitmap getBitmap(byte [] bitmapdata){
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    ByteArrayInputStream inStream = new ByteArrayInputStream(bitmapdata);
    BitmapFactory.decodeStream(inStream, null, options);
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, 50, 50);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    Bitmap bmp = BitmapFactory.decodeStream(inStream,null,options);
    return bmp;
}

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

}

【问题讨论】:

  • 尝试设置在Manifest.xml<application android:largeHeap="true">...
  • 仍然出现同样的错误

标签: android


【解决方案1】:

我在 ListView 中遇到了同样的问题。我通过在离开活动时释放分配的内存来解决它。为此,我为每个显示的位图调用了“recycle()”方法。

private List<Bitmap> m_displayedBitmaps = new ArrayList<Bitmap>();

private List<ImageView> m_displayedGridElements = new ArrayList<ImageView>();

// protected void onPause() {
public void onStop() {

    // don't forget to free the references to your bitmap
    for (ImageView currentGridElement : m_displayedGridElements) {
        currentGridElement.setImageBitmap(null);
    }
    m_displayedGridElements.clear();

    // recycle each image
    for (Bitmap currentBitmap : m_displayedBitmaps) {
        currentBitmap.recycle();
    }
    // clear the list
    m_displayedBitmaps.clear();



    super.onStop();
}

【讨论】:

    【解决方案2】:

    Android 的图像内存管理非常糟糕。所以你需要非常小心地处理图像。幸运的是,您可以尝试使用外部库来处理图像显示。试试通用图片加载器UIL

    【讨论】:

      【解决方案3】:

      您不应该在 SQLite 中存储图像。而是使用像Glide/Picasso 这样的图像加载/缓存库,它们都非常易于使用并且开箱即用地缓存图像。

      【讨论】:

        猜你喜欢
        • 2023-03-20
        • 2014-05-28
        • 1970-01-01
        • 2013-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        相关资源
        最近更新 更多