安卓商店物品App开发:如何将图库图片存入SQLite(BLOB)并在ImageView显示?
嘿,作为编程新手能做到这一步已经超棒啦!我来帮你一步步搞定从图库选图存入SQLite、再在详情页展示的完整流程~
第一步:从系统图库选择图片
首先我们需要启动系统图库的Intent,获取用户选中图片的Uri,再把它转换成字节数组(因为SQLite的BLOB类型存的是二进制数据)。
方式1:传统的startActivityForResult(适合旧版本Android)
先定义一个请求常量:
private static final int PICK_IMAGE_REQUEST = 100;
然后在需要触发选图的按钮点击事件里添加:
// 启动图库选择图片 Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, PICK_IMAGE_REQUEST);
接着重写onActivityResult方法处理返回结果:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null) { Uri imageUri = data.getData(); try { // 将Uri转换成InputStream,再转成字节数组 InputStream inputStream = getContentResolver().openInputStream(imageUri); byte[] imageBytes = getBytes(inputStream); // 调用数据库方法存入图片,itemId是当前物品的ID,需要你自己传递过来 updateItemImage(itemId, imageBytes); } catch (IOException e) { e.printStackTrace(); } } } // 工具方法:把InputStream转成byte数组 private byte[] getBytes(InputStream inputStream) throws IOException { ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int len; while ((len = inputStream.read(buffer)) != -1) { byteBuffer.write(buffer, 0, len); } return byteBuffer.toByteArray(); }
方式2:AndroidX推荐的registerForActivityResult(更安全)
如果你的项目用的是AndroidX,可以用这个方式替代上面的代码:
// 初始化ActivityResultLauncher ActivityResultLauncher<Intent> pickImageLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK && result.getData() != null) { Uri imageUri = result.getData().getData(); try { InputStream inputStream = getContentResolver().openInputStream(imageUri); byte[] imageBytes = getBytes(inputStream); updateItemImage(itemId, imageBytes); } catch (IOException e) { e.printStackTrace(); } } } ); // 触发选图时调用 Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); pickImageLauncher.launch(intent);
第二步:将图片字节数组存入SQLite数据库
你已经在数据库里创建了BLOB列,现在需要写一个更新(或插入)方法把字节数组存进去。假设你的数据库帮助类是DbHelper,添加如下方法:
// 更新指定物品的图片 public void updateItemImage(int itemId, byte[] imageBytes) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("image_blob", imageBytes); // 替换成你实际的BLOB列名 // 执行更新操作,where条件根据物品ID匹配 db.update("items", values, "id = ?", new String[]{String.valueOf(itemId)}); db.close(); } // 如果是插入新物品时存图片,就在insert方法里加values.put("image_blob", imageBytes);
第三步:从数据库读取图片并在详情页展示
在你的详情Activity里,先获取传递过来的物品ID,再从数据库取出字节数组,转换成Bitmap后设置给ImageView:
首先在DbHelper里添加读取图片的方法:
// 根据物品ID获取图片字节数组 public byte[] getItemImage(int itemId) { SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query("items", new String[]{"image_blob"}, // 只查BLOB列 "id = ?", new String[]{String.valueOf(itemId)}, null, null, null); byte[] imageBytes = null; if (cursor.moveToFirst()) { imageBytes = cursor.getBlob(cursor.getColumnIndexOrThrow("image_blob")); } cursor.close(); db.close(); return imageBytes; }
然后在详情Activity的onCreate方法里:
// 获取从列表页传递过来的物品ID int itemId = getIntent().getIntExtra("ITEM_ID", -1); DbHelper dbHelper = new DbHelper(this); byte[] imageBytes = dbHelper.getItemImage(itemId); ImageView itemImageView = findViewById(R.id.item_detail_image); // 替换成你详情页的ImageView ID if (imageBytes != null) { // 将字节数组转换成Bitmap Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); itemImageView.setImageBitmap(bitmap); } else { // 如果没有图片,设置一张默认图 itemImageView.setImageResource(R.drawable.default_item_pic); }
一些实用提示
- 性能优化:其实SQLite存BLOB不是最优方案,尤其是大尺寸图片,会让数据库体积暴涨、查询变慢。等你熟练后,可以改成存图片文件的路径到数据库,而不是存二进制数据。不过作为新手,先实现功能是第一位的~
- 图片压缩:如果用户选的图片太大,存入前记得压缩,避免占用过多空间。比如加个压缩方法:
// 压缩Bitmap的工具方法 private byte[] compressBitmap(Bitmap bitmap) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); // 第二个参数是压缩质量(0-100),JPEG格式会损失画质,PNG是无损但体积大 bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream); return stream.toByteArray(); }
然后在获取到InputStream后,先转成Bitmap再压缩:
Bitmap bitmap = BitmapFactory.decodeStream(inputStream); byte[] compressedBytes = compressBitmap(bitmap); updateItemImage(itemId, compressedBytes);
- 权限处理:Android 6.0及以上需要动态申请
READ_EXTERNAL_STORAGE权限,否则无法读取图库图片。可以在启动选图前先检查权限:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 101); } else { // 权限已获取,启动选图 pickImageLauncher.launch(intent); }
内容的提问来源于stack exchange,提问作者ShashankAC
相关产品推荐
相关产品推荐

