【问题标题】:Bitmap to byte[] to SQL and backwards位图到 byte[] 到 SQL 和向后
【发布时间】:2018-06-16 14:06:53
【问题描述】:

我正在创建应用程序,您可以在其中添加包含图像和一些数据的项目,然后将该项目的数据存储在 SQLite 数据库中。我想要这样做的方法是从 android 设备的图库中选择图像,将其转换为字节 [],以便我可以将其作为 Blob 存储在 SQLiteDataBase 中。为此,我必须将位图压缩为 byte[],这需要大量内存,因此我尝试将其作为 AsyncTask 执行。 现在我的威胁是,当我尝试从数据库中检索图像的字节 [] 并将其解码为位图时,它会占用大量内存,并且显示数据的列表视图非常滞后,甚至会使应用程序崩溃。你知道我怎样才能让它更好地工作吗? 这是我的应用程序的一些代码。

public class CompressImage extends AsyncTask<Bitmap, Void, byte[]> {

@Override
protected byte[] doInBackground(Bitmap... bitmaps) {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    bitmaps[0].compress(Bitmap.CompressFormat.JPEG, 20, outputStream);
    return outputStream.toByteArray();
}

插入特定项目数据的代码:

private void insertFlower() {
    CompressImage compressImage = new CompressImage();

    String name = mFlowerName.getText().toString().trim();
    String price = mFlowerPrice.getText().toString().trim();
    String quantity = mFlowerQuantity.getText().toString().trim();

    ContentValues contentValues = new ContentValues();
    contentValues.put(FlowersEntry.COLUMN_FLOWER_NAME, name);
    contentValues.put(FlowersEntry.COLUMN_FLOWER_PRICE, price);
    contentValues.put(FlowersEntry.COLUMN_FLOWER_TYPE, mType);
    contentValues.put(FlowersEntry.COLUMN_FLOWER_QUANTITY, quantity);
    contentValues.put(FlowersEntry.COLUMN_FLOWER_IMAGE, compressImage.doInBackground(bitmap));

    getContentResolver().insert(FlowersEntry.CONTENT_URI, contentValues);
}

当我从数据库中解析数据时,主要问题出现了,而且需要很长时间......

public class FlowersCursorAdapter extends CursorAdapter {

public FlowersCursorAdapter(Context context, Cursor c) {
    super(context, c, 0);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
    return LayoutInflater.from(context).inflate(R.layout.list_item, viewGroup, false);
}


@Override
public void bindView(View view, Context context, Cursor cursor) {
    TextView nameTextView = (TextView) view.findViewById(R.id.flowers_name);
    TextView priceTextView = (TextView) view.findViewById(R.id.flowers_price);
    TextView quantityTextView = (TextView) view.findViewById(R.id.flowers_quantity);
    ImageView imageImageView = (ImageView) view.findViewById(R.id.flowers_image);

    String nameFromDb = cursor.getString(cursor.getColumnIndex(FlowersEntry.COLUMN_FLOWER_NAME));
    String priceFromDb = String.valueOf(cursor.getFloat(cursor.getColumnIndex(FlowersEntry.COLUMN_FLOWER_PRICE)));
    String quantityFromDb = String.valueOf(cursor.getInt(cursor.getColumnIndex(FlowersEntry.COLUMN_FLOWER_QUANTITY)));
    byte[] byteFromDb = cursor.getBlob(cursor.getColumnIndex(FlowersEntry.COLUMN_FLOWER_IMAGE));

    Bitmap bitmapImage = BitmapFactory.decodeByteArray(byteFromDb, 0, byteFromDb.length);


    nameTextView.setText(nameFromDb);
    priceTextView.setText(priceFromDb);
    quantityTextView.setText(quantityFromDb);
    Glide.with(view.getContext()).load(bitmapImage).into(imageImageView);

}

【问题讨论】:

  • 位图的平均大小是多少?
  • 我猜 pskink 暗示的是,由于图像的大小和 IO 开销(加上缓存使用不当),将图像存储在数据库中可能会出现问题,例如光标窗口限制为 2M。将图像的路径存储在数据库中,提取它然后从其路径中检索实际图像被认为是更好的做法。
  • @MikeT 总的来说我不能同意,但是:sqlite.org/fasterthanfs.html 和/或sqlite.org/intern-v-extern-blob.html
  • @pskink 我在从数据库解码后检查了 bitmapImage.getByteCount() ,如果我做对了,它等于 48794880 什么是 46.5MB,但我不知道为什么会这样如果我从手机的图库中加载图片并且照片的平均重量为 3.50MB。
  • 无论如何我想我会尝试@MikeT 关于在数据库中存储路径的想法。

标签: android arrays database sqlite bitmap


【解决方案1】:

尝试在 bindView 中使用 bitmapImage 后添加此行。

bitmapImage.recycle();

【讨论】:

  • 我认为 Glide Library 自动解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2012-04-06
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
相关资源
最近更新 更多