java - 当gridview有很多项目时,"out of memory"问题

标签 java android gridview bitmap out-of-memory

嗨,我有一个 GridView (它有两个文本框和一个 ImageView ) 这些项目是从 db 填充的。对于没有照片的元素,我使用标准照片。应用程序适用于 50 个项目,但适用于 200 个项目时会出现一些错误。

  • logcat** java.lang.OutOfMemoryError 位于 android.graphics.BitmapFactory.nativeDecodeStream( native 方法)位于 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:652)

我尝试了一些从谷歌建议的方法来加载大位图,但它不起作用。 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

当我将 inJustDecodeBounds 设置为 true 时,应用程序可以运行,但所有项目都为空。 这是我的代码从数据库获取信息:

private void refreshList(String sql)
{
    gridArray = new ArrayList<Stock>();
    final Cursor cursor = _SQLite.RawQueryTry(sql, null);
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 2;

    if (cursor != null)
    {
        if (cursor.moveToFirst())
        {
            for (int i = 0; i < cursor.getCount(); i++)
            {
                byte[] blob = cursor.getBlob(cursor.getColumnIndex("FOTO"));
                Bitmap stockImage = null;
                ByteArrayInputStream inputStream = null;

                if (blob == null)
                {
                    options.inJustDecodeBounds=false;
                    stockImage = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.foto_yok, options);
                }
                else
                {
                    inputStream = new ByteArrayInputStream(blob);
                    stockImage = BitmapFactory.decodeStream(inputStream, null, options);

                }
                String stockName = cursor.getString(cursor.getColumnIndex("STOK_ADI"));
                String stockNo = cursor.getString(cursor.getColumnIndex("STOK_NO"));
                String stockCode = cursor.getString(cursor.getColumnIndex("STOK_KODU"));
                String stockEntity = cursor.getString(cursor.getColumnIndex("BIRIM"));
                String stockKdvOranı = cursor.getString(cursor.getColumnIndex("KDV_ORANI"));
                String stockRatio = TableUtils.getFieldValue("KATSAYI", "BIRIM", stockEntity, "STOKBIRI");
                String stockAmount = cursor.getString(cursor.getColumnIndex("MIKTAR"));
                gridArray.add(new Stock(stockImage, stockName, stockNo, stockCode, stockKdvOranı, stockEntity, stockAmount, stockRatio, processNo));

                cursor.moveToNext();
            }
        }
    }

    gridAdapter = new AdapterStockGridView(this, R.layout.stockgriditems, gridArray);
    gridView.setAdapter(gridAdapter);

}

和我的适配器类:

public class AdapterStockGridView extends ArrayAdapter<Stock>
{
    Context context;
    int id;
    ArrayList<Stock> stock = new ArrayList<Stock>();

    public AdapterStockGridView(Context context, int id, ArrayList<Stock> stock)
    {
        super(context, id, stock);
        this.id = id;
        this.context = context;
        this.stock = stock;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;
        RecordHolder holder = null;

        if (row == null)
        {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(id, parent, false);

            holder = new RecordHolder();
            holder.stockCode = (TextView) row.findViewById(R.id.stockCode);
            holder.stockName = (TextView) row.findViewById(R.id.stockName);
            holder.stockImage = (ImageView) row.findViewById(R.id.stockImage);
            row.setTag(holder);
        }
        else
        {
            holder = (RecordHolder) row.getTag();
        }

        Stock item = stock.get(position);
        holder.stockCode.setText(item.getStockCode());
        holder.stockName.setText(item.getStockName());
        holder.stockImage.setImageBitmap(item.getStockImage());

        return row;

    }

}

static class RecordHolder
{
    TextView stockName;
    TextView stockCode;
    ImageView stockImage;

}

}

最佳答案

也许您将 blob 存储为全尺寸?如果是这样,则无需这样做,因为您浪费了太多空间并且遇到了这些内存问题。无论如何,用户都不会看到大图像,因此请重新进行图像存储,以便将缩小的图像存储为 blob。

您得到这些 OOE 是因为您正在加载完整的 blob 字节数组 - 按照现在的方式,您无法使用开发人员文章中的文章。

此外,请勿将图像加载到该 Stock 对象中,因为您将不必要地保存它们。相反,使用位图加载器机制将图像保存在 LRUCache 中,如果在那里找不到,则会从数据库加载它们。在您的 GridView 适配器 getView 方法中请求加载该图像。如果在LRUCache中找到,则从那里获取它,如果没有启动AsyncTask从DB中获取它,则将其添加到LRUCache中并显示给用户。

这里是a link使用 LRUCache 缓存位图。

关于java - 当gridview有很多项目时,"out of memory"问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18586268/

相关文章:

java - 如何在矩形内写文字

android - apk文件中的签名和证书有什么区别?

android - 具有国家代码下拉列表(国际电话输入)的移动设备上的 CSS 问题

gridview - 如何在 Yii2 gridview 中连接两个表并获取值

java - 使用 Java 连接到 Oracle DSN 时出错

java "redundant"包装类?

php - 防止 GridView ActionColumn 图标全局换行

c# - 我怎样才能在 gridview 中获取超链接的值(value)?

java - 如何在 Java 中将 Unchecked Exception 转换为 Checked Exception,反之亦然

android - 在应用程序生命周期的早期调用 getPackageName()