我已经研究这个问题好几天了,但我不知道我做错了什么。我正在为一个项目制作一个库存/商店应用程序,用户可以将他们库存的商品输入到列表中。根据要求,我需要赋予它拍照功能,并且我需要能够将图片保存在 SQLite 数据库中。这部分我已经实现了。但是,当我尝试更新某个项目并将其再次保存到列表中时,图像返回 null。我附上了图片来直观地解释...
主要 Activity
新项目页面
将项目保存到主要 Activity ListView
点击要编辑的项目
除非我拍摄新照片,否则当我保存更新的项目时,图标图像将返回 null
我正在使用 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 方法中,但如果您想查看整个文件,请告诉我。
最佳答案
这项工作的最佳方法是,您应该将图像保存在手机目录中,根据您的要求,该目录可从图库访问/不可访问,并将文件路径保存在图像列中,这样您就可以在需要加载时访问该图像。我也在我的一个离线应用程序中遵循相同的方法,该方法运行顺利,没有任何问题,但请确保每当您对任何行执行删除选项时,此时您还应该删除该文件以实现更好的存储管理。
关于java - 图像不会保留在我的数据库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47345532/