如何将图片Uri或Bitmap适配为SQLite插入方法的int类型参数以实现图片存储?
解决SQLite存储相册图片的类型不匹配问题
兄弟,你现在的核心问题是数据库存储图片的思路错了——int类型只能存储像R.drawable.xxx这种APP内置资源的ID,根本存不了从相册选来的图片内容。想要把图片存入SQLite,必须把图片转成二进制字节数组(byte[]),然后用SQLite的BLOB类型字段来存储。下面给你一步步修正的方案:
1. 修改数据库表结构(SQ_Lite_DB类中)
首先要把原来存图片的int类型字段改成BLOB类型,在onCreate方法里的建表语句要更新:
@Override public void onCreate(SQLiteDatabase db) { // 把image字段类型从INTEGER改成BLOB String createTable = "CREATE TABLE orders (id INTEGER PRIMARY KEY AUTOINCREMENT, image BLOB, name TEXT)"; db.execSQL(createTable); }
如果已经创建过表,记得要么卸载重装APP,要么在onUpgrade里处理表结构更新(比如删除旧表重建,或者添加字段)。
2. 修正insertData方法的参数和逻辑
把原来接收int类型图片的参数改成byte[],同时注意写入数据库要用getWritableDatabase()(之前用getReadableDatabase()虽然能凑合用,但写入操作明确用前者更规范):
public boolean insertData(byte[] image, String name){ SQLiteDatabase database = getWritableDatabase(); ContentValues values = new ContentValues(); values.put("image", image); values.put("name", name); long id = database.insert("orders", null, values); database.close(); return id > 0; }
3. 在onActivityResult中调用修正后的方法
你已经把Bitmap转成了byte[],现在直接把这个数组传给insertData就行,同时修正代码里的小错误(比如editText的拼写和getText()的调用):
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); edittext = findViewById(R.id.edittext); SQ_Lite_DB db = new SQ_Lite_DB(SQLite.this); if (resultCode == RESULT_OK && requestCode == 11){ try { InputStream inputStream = getContentResolver().openInputStream(data.getData()); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); // 可选:如果图片太大,建议先缩放压缩,避免数据库体积暴涨 int targetSize = 500; float scale = Math.min((float)targetSize/bitmap.getWidth(), (float)targetSize/bitmap.getHeight()); Matrix matrix = new Matrix(); matrix.postScale(scale, scale); Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); ByteArrayOutputStream baos = new ByteArrayOutputStream(); scaledBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] img = baos.toByteArray(); // 调用修正后的insertData方法 boolean isSuccess = db.insertData(img, edittext.getText().toString()); Toast.makeText(this, isSuccess ? "数据插入成功" : "插入失败", Toast.LENGTH_SHORT).show(); // 插入成功后记得刷新RecyclerView的数据,让新内容显示出来 // 比如重新调用ReadSqliteData更新list,然后通知adapter刷新 } catch (FileNotFoundException e) { e.printStackTrace(); Toast.makeText(this, "读取图片失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); Log.d("tag", e.getMessage()); } } }
4. 读取数据时转成Bitmap的补充
之后从数据库读取图片时,要把BLOB转回Bitmap,比如在你的ReadSqliteData方法里:
// 假设cursor是查询结果 byte[] imageBytes = cursor.getBlob(cursor.getColumnIndexOrThrow("image")); Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); // 把bitmap传给Model,再刷新RecyclerView
最后提醒
- 不要每次操作数据库都新建
SQ_Lite_DB实例,建议在Activity里全局持有一个,减少资源开销 - 大图片存SQLite会导致数据库体积急剧增大,甚至影响性能,所以压缩很有必要;如果图片很多,更推荐只存图片的Uri路径到数据库,图片本身存在外部存储里,这样更高效
内容的提问来源于stack exchange,提问作者Sachin Burdak
相关产品推荐
相关产品推荐

