【问题标题】:Update Android Image Bitmap to SQLite Blob将 Android 图像位图更新为 SQLite Blob
【发布时间】:2017-06-10 10:23:48
【问题描述】:

我试图找出我在哪里出错,无论是编码还是逻辑缺陷,我创建了一个食谱应用程序,它需要几个字符串和一个图像,所有数据都保存到数据库中,在主屏幕上我得到一个列表来自数据库的食谱。

主屏幕

添加/编辑屏幕

创建或添加新数据按预期工作,所有数据都已保存。问题是除了图像之外的所有内容都可以更新,一旦保存,任何第二次尝试似乎都不会影响图像,图像保持不变。

核心原则是将数据设置到视图(当用户启动活动 onCreate 或恢复活动 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;
}

我可以更新字符串数据但保存后无法真正更新图像,这可能是什么问题?

【问题讨论】:

    标签: android sqlite android-bitmap android-imagebutton


    【解决方案1】:

    经过大量研究和测试,问题只是图像按钮无法重置。

    image.setBackground(bitmapDrawable);
    

    上面的这个方法似乎不适用于更新,我的快速解决方法是简单地保留代码原样并简单地添加检测onActivityResult以确定它是否真的是更新,然后将字节数据直接添加到数据库,而不是更新图像按钮然后recreate() Activity,过程昂贵,但对于简单的应用程序来说并不昂贵。

    if (rowId != null) {
                    ...
                    recipe.setImage(DbBitmapUtility.getBytes(imageBitmap));
                    recipeDAOImp.updateRecipe(recipe);
                    recreate();
                }
    

    一切正常。

    【讨论】:

      【解决方案2】:

      我的猜测是问题出在您的 DAO 代码中。我有一个类似的设置(带有 text 和 blob 列的 sqlite 表,都得到更新),所以我知道你想要做的事情是可能的。

      【讨论】:

      • 问题不在DAO代码中,我已经编辑了问题以包含更新部分,看看,问题是代码工作它只是我无法理解的逻辑工作呢。它是一个简单的应用程序,因此所有数据都从模块到视图,从视图到模块,创建都很好,但更新不行,图像一旦设置就不会改变。除了我提到的内容之外,也许重写或其他一些逻辑可能会有所帮助并且可以接受。
      • 尝试改变从 Bundle 中获取新位图的方式。您可以尝试使用 Intent.getParcelableExtra (stackoverflow.com/a/12908133/678123),也可以将其作为字节数组 (stackoverflow.com/a/11010565/678123) 传递。
      • 不,如果您查看上面的代码,我只对 ID 感兴趣,如果在之前的活动中进行了选择,那么它是查看/编辑模式,如果没有选择/ID 为空,那么它是新的/Creation 模式是唯一传递 extras.getLong(RecipeDAOImp.KEY_ID) 的方法,因为每个 Activity 处理自己的工作。所有数据都来自模块到视图,以及从视图到模块,但图像一旦设置,一旦保存在数据库中就不会改变。我可以从相机获取图像并设置为图像按钮,但是一旦保存从相机拍摄的图像将不会更新图像按钮,图像已经来自数据库。感谢您的意见。
      • 我看到在#onCreate 你得到了一个ID;我更多地关注#onActivityResult,其中有“ Bitmap imageBitmap = (Bitmap) extras.get("data"); ”这一行,我认为这是无效的。你可以传递byte[],你可以传递ParcelableExtra,但不能传递Bitmap。抱歉我不能提供解决方案,只希望你想做的事情是可能的:)
      • 不,onActivityResult 是正确的并且正在工作,如果不是,我将无法首先保存任何图像,在相机返回数据并转换后调用该方法将其设置为位图在保存到数据库之前将其设置为查看,就像我的代码和图片一样,您可以看到咖啡杯 :) 我想我将不得不重写或设置更新标志,感谢您的输入。
      猜你喜欢
      • 2012-01-11
      • 2013-03-28
      • 1970-01-01
      • 2013-03-21
      • 2011-08-30
      • 1970-01-01
      • 2012-04-28
      • 2015-05-28
      • 1970-01-01
      相关资源
      最近更新 更多