图像不会粘在我的数据库中

时间:2017-11-17 07:38:19

标签: java android sqlite android-sqlite

我已经在这个问题上工作了好几天,但我无法弄清楚我做错了什么。我为一个项目制作了一个库存/商店应用程序,用户可以将他们库存的商品输入到列表中。根据我的要求,我需要给它拍照功能,我需要能够将图片保存在SQLite数据库中。那部分我已经实现了。但是当我尝试更新项目并将其再次保存到列表时,图像返回null。我附上图片以便直观地解释......

主要活动

image1

新商品页面

image2

将项目保存到主要活动列表视图

image3

点击要修改的项目

image4

除非我拍摄新照片,否则当我保存更新的项目时,图标图像将返回null

image5

我正在使用CursorLoader。我对待图像的方式与处理数据库中所有其他列的方式相同...所以我无法弄清楚为什么它不会坚持下去。

这里是与EditorActivity中的图像有关的代码:

Bitmap photos;

// Content URI for the existing item (null if it's a new item)
private Uri mCurrentItemUri;

// Picture taking capability with button
public void takePicture(View view) {
    PackageManager pm = this.getPackageManager();
    if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    } else {
        Toast.makeText(EditorActivity.this, "Sorry! You don't have a camera app.", Toast.LENGTH_SHORT).show();
    }
}

// Once image is taken, save to image view and then save to db as a ByteArray
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        Bundle extras = data.getExtras();
        photos = (Bitmap) extras.get("data");
        mImageView.setImageBitmap(photos);
    }
}

// Get user input from editor and save item into database.
private void saveItem() {
    // Read from input fields
    // Use trim to eliminate leading or trailing white space
    String nameString = mNameEditText.getText().toString().trim();
    String priceString = mPriceEditText.getText().toString().trim();
    // Find quantity TV by id and extract int value as String
    TextView quantityTextView = (TextView) findViewById(R.id.quantity_editor_text_view);
    String quantityString = quantityTextView.getText().toString();
    ImageView iconImage = (ImageView) findViewById(R.id.image_view_editor);

    // Check if this is supposed to be a new item and check if all the fields in the editor are blank
    if (mCurrentItemUri == null && TextUtils.isEmpty(nameString)
            && TextUtils.isEmpty(priceString) && TextUtils.isEmpty(quantityString) && iconImage == null) {
        // Since no fields were modified, we can return early without creating a new item.
        // No need to create ContentValues and no need to do any ContentProvider operations.
        return;
    }

    // Create a ContentValues object where column names are the keys and item attributes from the editor are the values.
    ContentValues values = new ContentValues();

    // Find image by the member variable "photos" and get the bytes
    byte[] bytes = Utils.getImageBytes(photos);
    values.put(ItemEntry.IMAGE_VIEW, bytes);

    values.put(ItemEntry.COLUMN_NAME, nameString);

    int price = 0;
    if (!TextUtils.isEmpty(priceString)) {
        price = Integer.parseInt(priceString);
    }
    values.put(ItemEntry.COLUMN_PRICE, price);

    values.put(ItemEntry.COLUMN_QUANTITY, quantityString);

    // Determine if this is a new or existing item by checking if mCurrentItemUri is null or not
    if (mCurrentItemUri == null) {
        // This is a NEW item, so insert a new item into the provider,
        // returning the content URI for the new item.
        Uri newUri = getContentResolver().insert(ItemEntry.CONTENT_URI, values);
        // Show a toast message depending on whether or not the insertion was successful.
        if (newUri == null) {
            // If the new content URI is null, then there was an error with insertion.
            Toast.makeText(this, getString(R.string.insert_item_failed), Toast.LENGTH_SHORT).show();
        } else {
            // Otherwise, the insertion was successful and we can display a toast.
            Toast.makeText(this, getString(R.string.insert_item_successful), Toast.LENGTH_SHORT).show();
        }
    } else {
        // Otherwise this is an EXISTING item, so update the item with content URI: mCurrentItemUri
        // and pass in the new ContentValues. Pass in null for the selection and selection args
        // because mCurrentItemUri will already identify the correct row in the database that
        // we want to modify.
        int rowsAffected = getContentResolver().update(mCurrentItemUri, values, null, null);
        // Show a toast message depending on whether or not the update was successful.
        if (rowsAffected == 0) {
            // If no rows were affected, then there was an error with the update.
            Toast.makeText(this, getString(R.string.edit_item_failed), Toast.LENGTH_SHORT).show();
        } else {
            // Otherwise, the update was successful and we can display a toast.
            Toast.makeText(this, getString(R.string.edit_item_successful), Toast.LENGTH_SHORT).show();
        }
    }
}

用于图像方法的Utils文件:

public class Utils {

// Used in saveItem
// Adding the if/else statement here allows the picture to be null
// But now the picture disappears when you update an item without taking a new pic.
public static byte[] getImageBytes(Bitmap bitmap) {
    if (bitmap != null) {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        return stream.toByteArray();
    } else {
        return null;
    }
}

// Used in OnLoadFinished (Editor) and cursor adapter
public static Bitmap getImage(byte[] image) {
    return BitmapFactory.decodeByteArray(image, 0, image.length);
}
}

我相当肯定问题出在saveItem方法中,但如果您想查看整个文件,请告诉我。

2 个答案:

答案 0 :(得分:0)

这项工作的最佳方法是,您应该将图像保存在手机目录中,该目录可根据您的要求从图库中访问/无法访问,并将文件路径保存在图像列中,您可以在需要时访问该图像加载。我也在我的一个离线应用程序中遵循相同的方法,它可以顺利运行但没有任何问题,但确保无论何时执行任何行的删除选项,那么您还应该删除该文件以便更好地进行存储管理。

答案 1 :(得分:0)

发布以防万一。问题不在我想象的地方。在EditorActivity的onLoadFinished方法中,我需要添加以下行:

photos = Utils.getImage(image);

从光标获取blob后。这样可以在更新项目后保留图片,而无需拍摄新照片。

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {

    // Bail early if the cursor is null or there is less than 1 row in the cursor
    if (cursor == null || cursor.getCount() < 1) {
        return;
    }

    // Proceed with moving to the first row of the cursor and reading data from it
    // (This should be the only row in the cursor)
    if (cursor.moveToFirst()) {
        // Find the columns of item attributes that we're interested in
        int imageColumnIndex = cursor.getColumnIndex(ItemEntry.IMAGE_VIEW);
        int nameColumnIndex = cursor.getColumnIndex(ItemEntry.COLUMN_NAME);
        int priceColumnIndex = cursor.getColumnIndex(ItemEntry.COLUMN_PRICE);
        int quantityColumnIndex = cursor.getColumnIndex(ItemEntry.COLUMN_QUANTITY);

        // Extract out the value from the Cursor for the given column index
        byte[] image = cursor.getBlob(imageColumnIndex);
        // populate the photos variable with bytes and the picture will save to the list view after editing item
        photos = Utils.getImage(image);
        String name = cursor.getString(nameColumnIndex);
        String price = cursor.getString(priceColumnIndex);
        int quantity = cursor.getInt(quantityColumnIndex);

        // Update the views on the screen with the values from the database
        // if I delete the if/else statement, error saying Attempt to get length of null array from method Utils.getImage
        // can remove once I get image to stick
        if (image != null) {
            mImageView.setImageBitmap(Utils.getImage(image));
        } else {
            mImageView.setImageBitmap(null);
        }
        mNameEditText.setText(name);
        mPriceEditText.setText(price);
        mQuantityTextView.setText(Integer.toString(quantity));
    }
}