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

Java 图像不会粘在我的数据库中,java,android,sqlite,android-sqlite,Java,Android,Sqlite,Android Sqlite,我已经研究这个问题好几天了,我不知道我做错了什么。我正在为一个项目制作一个库存/商店应用程序,用户可以在列表中输入他们的库存物品。根据要求,我需要给它拍照的能力,我需要能够保存在SQLite数据库的图片。我已经做到了这一点。但当我尝试更新一个项目并将其再次保存到列表中时,图像返回null。我附上了一些图片来直观地解释 主要活动 新项目页面 将项目保存到主活动列表视图中 单击要编辑的项目 除非我拍摄一张新照片,否则当我保存更新的项目时,图标图像将返回null 我用的是游标载入器。我处理图

我已经研究这个问题好几天了,我不知道我做错了什么。我正在为一个项目制作一个库存/商店应用程序,用户可以在列表中输入他们的库存物品。根据要求,我需要给它拍照的能力,我需要能够保存在SQLite数据库的图片。我已经做到了这一点。但当我尝试更新一个项目并将其再次保存到列表中时,图像返回null。我附上了一些图片来直观地解释

主要活动

新项目页面

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

单击要编辑的项目

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

我用的是游标载入器。我处理图像的方式与处理数据库中所有其他列的方式相同。。。所以我不明白为什么它粘不住

以下是有关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方法上,但如果您想查看整个文件,请告诉我。

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

这项工作的最佳方法是,您应该将图像保存在电话目录中可根据您的要求从gallery访问/不可访问,并将文件路径保存在“图像”列中,您可以在需要加载图像时访问该图像。在我的一个离线应用程序中,我也采用了相同的方法,该方法工作顺利,没有任何问题,但请确保每当您对任何行执行删除选项时,您也应该删除该文件,以便更好地进行存储管理。

发布,以防对任何人有所帮助。问题不在我想的地方。在EditorActivity中的onLoadFinished方法中,我需要添加以下行:

photos = Utils.getImage(image);
刚从光标中获取斑点。这样,在更新项目后,图片就可以保留下来,而无需拍摄新图片

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));
    }
}
public void onLoadFinished(加载器,光标){
//如果光标为空或光标中的行少于1行,则提前退出
if(cursor==null | | cursor.getCount()<1){
返回;
}
//继续移动到光标的第一行并从中读取数据
//(这应该是光标中的唯一一行)
if(cursor.moveToFirst()){
//查找我们感兴趣的项目属性列
int imageColumnIndex=cursor.getColumnIndex(ItemEntry.IMAGE\u视图);
int nameColumnIndex=cursor.getColumnIndex(ItemEntry.COLUMN\u NAME);
int priceColumnIndex=cursor.getColumnIndex(ItemEntry.COLUMN\u PRICE);
int quantityColumnIndex=cursor.getColumnIndex(ItemEntry.COLUMN\u QUANTITY);
//从游标中提取给定列索引的值
字节[]image=cursor.getBlob(imageColumnIndex);
//用字节填充photos变量,编辑项目后,图片将保存到列表视图
photos=Utils.getImage(image);
字符串名称=cursor.getString(nameColumnIndex);
String price=cursor.getString(priceColumnIndex);
int数量=cursor.getInt(quantityColumnIndex);
//使用数据库中的值更新屏幕上的视图
//如果删除if/else语句,则会出现以下错误:尝试从方法Utils.getImage获取null数组的长度
//可以删除一旦我得到图像粘贴
如果(图像!=null){
setImageBitmap(Utils.getImage(image));
}否则{
mImageView.setImageBitmap(空);
}
mNameEditText.setText(名称);
mpriceeditext.setText(价格);
mQuantityTextView.setText(整数.toString(数量));
}
}

发布,以防对任何人有所帮助。问题不在我想的地方。在EditorActivity中的onLoadFinished方法中,我需要添加以下行:

photos = Utils.getImage(image);
刚从光标中获取斑点。这样,在更新项目后,图片就可以保留下来,而无需拍摄新图片

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));
    }
}
public void onLoadFinished(加载器,光标){
//如果光标为空或光标中的行少于1行,则提前退出
if(cursor==null | | cursor.getCount()<1){
返回;
}
//继续移动到光标的第一行并从中读取数据
//(这应该是光标中的唯一一行)
if(cursor.moveToFirst()){
//查找我们感兴趣的项目属性列
int imageColumnIndex=cursor.getColumnIndex(ItemEntry.IMAGE\u视图);
int nameColumnIndex=cursor.getColumnIndex(ItemEntry.COLUMN\u NAME);
int priceColumnIndex=cursor.getColumnIndex(ItemEntry.COLUMN\u PRICE);
int quantityColumnIndex=cursor.getColumnIndex(ItemEntry.COLUMN\u QUANTITY);
//从游标中提取给定列索引的值
字节[]image=cursor.getBlob(imageColumnIndex);
//用字节填充photos变量,编辑项目后,图片将保存到列表视图
photos=Utils.getImage(image);
字符串名称=cursor.getString(nameColumnIndex);
String price=cursor.getString(priceColumnIndex);
int数量=cursor.getInt(quantityColumnIndex);
//更新屏幕上的视图