将 Android 图像位图更新为 SQLite Blob
Update Android Image Bitmap to SQLite Blob
我想弄清楚我哪里出错了,要么是编码错误,要么是逻辑缺陷,我创建了一个食谱应用程序,它接受几个字符串和一个图像,所有数据都保存到数据库中,在主屏幕上我得到了一个来自数据库的食谱列表。
主屏幕
添加/编辑屏幕
创建或添加新数据按预期进行,所有数据都已保存。问题是,除了图像之外的所有内容都可以在保存后更新,任何第二次尝试似乎都不会影响图像,图像保持不变。
核心原理是将数据设置到视图(当用户启动activity onCreate或恢复activity onResume时)并从视图中获取数据(当用户离开onPause和onSaveInstanceState时以防更新)
代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_edit);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableEdit();
fab.hide();
}
});
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
recipeDAOImp = new RecipeDAOImp(this);
recipeDAOImp.open();
findViews();
rowId = (savedInstanceState == null) ? null :
(Long) savedInstanceState.getSerializable(RecipeDAOImp.KEY_ID);
if (rowId == null) {
Bundle extras = getIntent().getExtras();
rowId = extras != null ? extras.getLong(RecipeDAOImp.KEY_ID)
: null;
}
populateData();
disableEdit();
}
private void findViews() {
// Finds Views and Set onClick to imageButton
}
private void disableEdit() {
// Disable Views
}
private void enableEdit() {
// Enables Views
}
private void populateData() {
// If rowId is available then user is trying to Edit Recipe
if (rowId != null) {
setTitle("Edit Recipe");
Recipe recipe = new Recipe(rowId);
Cursor cursor = recipeDAOImp.getRecipe(recipe);
startManagingCursor(cursor);
title.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_TITLE)));
ingredients.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_INGREDIENTS)));
steps.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_STEPS)));
category.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_CATEGORY)));
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), DbBitmapUtility.getImage(cursor.getBlob(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_IMAGE))));
image.setBackground(bitmapDrawable);
// Else user is Adding a new Recipe
} else {
fab.hide();
setTitle("Add Recipe");
enableEdit();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveState();
outState.putSerializable(RecipeDAOImp.KEY_ID, rowId);
}
@Override
protected void onPause() {
super.onPause();
saveState();
}
@Override
protected void onResume() {
super.onResume();
populateData();
}
private void saveState() {
// Get the values from the views
String titleString = title.getText().toString();
String ingredientString = ingredients.getText().toString();
String stepsString = steps.getText().toString();
String categoryString = category.getText().toString();
// Get the image from imageButton
Drawable drawable = image.getBackground();
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
byte[] imageData = DbBitmapUtility.getBytes(bitmap);
// Just to clarify image is never null as the backround is a camre image
if (titleString.equals(null) || "".equals(titleString) || ingredientString.equals(null) || "".equals(ingredientString) || stepsString.equals(null) || "".equals(stepsString) || categoryString.equals(null) || "".equals(categoryString) || imageData.equals(null) || "".equals(imageData)) {
Toast.makeText(this, "No Data Saved", Toast.LENGTH_SHORT).show();
} else {
Recipe recipe = new Recipe(titleString, ingredientString, stepsString, categoryString, imageData);
// If rowId is not Available then user is Creating a new Recipe
if (rowId == null) {
long id = recipeDAOImp.createRecipe(recipe);
if (id > 0) {
rowId = id;
}
} else {
recipe.setId(rowId);
recipeDAOImp.updateRecipe(recipe);
}
}
}
@Override
public void onClick(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
// Set the imageButton
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), imageBitmap);
image.setBackground(bitmapDrawable);
}
}
}
DAO
@Override
public boolean updateRecipe(Recipe recipe) {
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_TITLE, recipe.getTitle());
contentValues.put(KEY_INGREDIENTS, recipe.getIngredients());
contentValues.put(KEY_STEPS, recipe.getSteps());
contentValues.put(KEY_CATEGORY, recipe.getCategory());
contentValues.put(KEY_IMAGE, recipe.getImage());
return sqLiteDatabase.update(DATABASE_TABLE, contentValues, KEY_ID + "=" + recipe.getId(), null) > 0;
}
我可以更新字符串数据但保存图像后无法真正更新图像,这可能是什么问题?
我猜问题出在您的 DAO 代码中。我有一个类似的设置(带有文本和 blob 列的 sqlite table,两者都会更新),所以我知道你正在尝试做的事情是可能的。
经过大量研究和测试,问题只是无法重置图像按钮。
image.setBackground(bitmapDrawable);
上面的这个方法似乎不适用于更新,我的快速修复只是简单地保留代码原样并简单地添加一个检测 onActivityResult
以确定它是否真的是一个更新,然后添加字节数据直接到数据库,而不是更新图像按钮,然后 recreate()
Activity,昂贵的过程,但对于一个简单的应用程序来说并不昂贵。
if (rowId != null) {
...
recipe.setImage(DbBitmapUtility.getBytes(imageBitmap));
recipeDAOImp.updateRecipe(recipe);
recreate();
}
一切按预期工作。
我想弄清楚我哪里出错了,要么是编码错误,要么是逻辑缺陷,我创建了一个食谱应用程序,它接受几个字符串和一个图像,所有数据都保存到数据库中,在主屏幕上我得到了一个来自数据库的食谱列表。
主屏幕
添加/编辑屏幕
创建或添加新数据按预期进行,所有数据都已保存。问题是,除了图像之外的所有内容都可以在保存后更新,任何第二次尝试似乎都不会影响图像,图像保持不变。
核心原理是将数据设置到视图(当用户启动activity onCreate或恢复activity onResume时)并从视图中获取数据(当用户离开onPause和onSaveInstanceState时以防更新)
代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_edit);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableEdit();
fab.hide();
}
});
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
recipeDAOImp = new RecipeDAOImp(this);
recipeDAOImp.open();
findViews();
rowId = (savedInstanceState == null) ? null :
(Long) savedInstanceState.getSerializable(RecipeDAOImp.KEY_ID);
if (rowId == null) {
Bundle extras = getIntent().getExtras();
rowId = extras != null ? extras.getLong(RecipeDAOImp.KEY_ID)
: null;
}
populateData();
disableEdit();
}
private void findViews() {
// Finds Views and Set onClick to imageButton
}
private void disableEdit() {
// Disable Views
}
private void enableEdit() {
// Enables Views
}
private void populateData() {
// If rowId is available then user is trying to Edit Recipe
if (rowId != null) {
setTitle("Edit Recipe");
Recipe recipe = new Recipe(rowId);
Cursor cursor = recipeDAOImp.getRecipe(recipe);
startManagingCursor(cursor);
title.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_TITLE)));
ingredients.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_INGREDIENTS)));
steps.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_STEPS)));
category.setText(cursor.getString(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_CATEGORY)));
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), DbBitmapUtility.getImage(cursor.getBlob(
cursor.getColumnIndexOrThrow(RecipeDAOImp.KEY_IMAGE))));
image.setBackground(bitmapDrawable);
// Else user is Adding a new Recipe
} else {
fab.hide();
setTitle("Add Recipe");
enableEdit();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveState();
outState.putSerializable(RecipeDAOImp.KEY_ID, rowId);
}
@Override
protected void onPause() {
super.onPause();
saveState();
}
@Override
protected void onResume() {
super.onResume();
populateData();
}
private void saveState() {
// Get the values from the views
String titleString = title.getText().toString();
String ingredientString = ingredients.getText().toString();
String stepsString = steps.getText().toString();
String categoryString = category.getText().toString();
// Get the image from imageButton
Drawable drawable = image.getBackground();
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
byte[] imageData = DbBitmapUtility.getBytes(bitmap);
// Just to clarify image is never null as the backround is a camre image
if (titleString.equals(null) || "".equals(titleString) || ingredientString.equals(null) || "".equals(ingredientString) || stepsString.equals(null) || "".equals(stepsString) || categoryString.equals(null) || "".equals(categoryString) || imageData.equals(null) || "".equals(imageData)) {
Toast.makeText(this, "No Data Saved", Toast.LENGTH_SHORT).show();
} else {
Recipe recipe = new Recipe(titleString, ingredientString, stepsString, categoryString, imageData);
// If rowId is not Available then user is Creating a new Recipe
if (rowId == null) {
long id = recipeDAOImp.createRecipe(recipe);
if (id > 0) {
rowId = id;
}
} else {
recipe.setId(rowId);
recipeDAOImp.updateRecipe(recipe);
}
}
}
@Override
public void onClick(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
// Set the imageButton
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), imageBitmap);
image.setBackground(bitmapDrawable);
}
}
}
DAO
@Override
public boolean updateRecipe(Recipe recipe) {
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_TITLE, recipe.getTitle());
contentValues.put(KEY_INGREDIENTS, recipe.getIngredients());
contentValues.put(KEY_STEPS, recipe.getSteps());
contentValues.put(KEY_CATEGORY, recipe.getCategory());
contentValues.put(KEY_IMAGE, recipe.getImage());
return sqLiteDatabase.update(DATABASE_TABLE, contentValues, KEY_ID + "=" + recipe.getId(), null) > 0;
}
我可以更新字符串数据但保存图像后无法真正更新图像,这可能是什么问题?
我猜问题出在您的 DAO 代码中。我有一个类似的设置(带有文本和 blob 列的 sqlite table,两者都会更新),所以我知道你正在尝试做的事情是可能的。
经过大量研究和测试,问题只是无法重置图像按钮。
image.setBackground(bitmapDrawable);
上面的这个方法似乎不适用于更新,我的快速修复只是简单地保留代码原样并简单地添加一个检测 onActivityResult
以确定它是否真的是一个更新,然后添加字节数据直接到数据库,而不是更新图像按钮,然后 recreate()
Activity,昂贵的过程,但对于一个简单的应用程序来说并不昂贵。
if (rowId != null) {
...
recipe.setImage(DbBitmapUtility.getBytes(imageBitmap));
recipeDAOImp.updateRecipe(recipe);
recreate();
}
一切按预期工作。