Android:Fragment内CircleImageView图片的SQLite存储读取问题
问题分析
你的核心问题集中在三个方面:
- 保存时没有传入默认图片的Bitmap,直接传了
null导致数据库图片字段为空,读取时触发崩溃 DatabaseHelper的getBitmapAsByteArray方法未处理null参数,会引发空指针异常- 读取图片时没有判断Blob是否为空,直接解码导致崩溃
下面是分步解决方案,附带修改后的完整代码:
1. 全局维护当前头像的Bitmap
在Fragment中声明全局变量,用来记录当前使用的头像(默认图或用户选择的图片),确保保存时能拿到正确的Bitmap:
private Bitmap mCurrentProfileBitmap; private CircleImageView mProfilePhoto; private EditText mNameInput; // 假设你有输入用户名的EditText
然后在onViewCreated中初始化默认图片:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mProfilePhoto = view.findViewById(R.id.your_circle_image_view_id); mNameInput = view.findViewById(R.id.your_username_input_id); // 加载默认图片到全局变量,初始化头像显示 mCurrentProfileBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.default_profile_image); mProfilePhoto.setImageBitmap(mCurrentProfileBitmap); }
2. 修复onActivityResult,更新全局Bitmap
修改相册选择后的逻辑,把选中的图片赋值给全局变量,确保后续保存时能拿到:
@Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == 0 && resultCode == Activity.RESULT_OK && data != null) { Uri path = data.getData(); try { mCurrentProfileBitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), path); mProfilePhoto.setImageBitmap(mCurrentProfileBitmap); } catch (IOException e) { e.printStackTrace(); // 图片加载失败时恢复默认图 mCurrentProfileBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.default_profile_image); mProfilePhoto.setImageBitmap(mCurrentProfileBitmap); } } }
3. 修复保存按钮的逻辑
点击保存时传入全局的mCurrentProfileBitmap,不再传null:
@Override public void onClick(View v) { switch (v.getId()){ case R.id.saveProfileButton: String username = mNameInput.getText().toString().trim(); if(!username.isEmpty()){ // 传入当前维护的头像Bitmap addUserInformation(username, mCurrentProfileBitmap); } else { toastMessage("请输入用户名"); } break; case R.id.profile_photo: Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); try { startActivityForResult(Intent.createChooser(i, "Select Picture"), 0); }catch (ActivityNotFoundException ex){ ex.printStackTrace(); } break; } }
4. 修复DatabaseHelper的空Bitmap处理
修改getBitmapAsByteArray方法,避免传入null时崩溃,同时优化图片压缩质量(0会严重失真,推荐80):
private static byte[] getBitmapAsByteArray(Bitmap bitmap) { if(bitmap == null){ return null; } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // 调整压缩质量,平衡图片清晰度和大小 bitmap.compress(Bitmap.CompressFormat.PNG, 80, outputStream); return outputStream.toByteArray(); }
同时优化addUserInformation方法,单用户场景下避免重复插入数据:
public boolean addUserInformation(String username, Bitmap picture){ if(username == null || username.trim().isEmpty()){ return false; } SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("USERNAME", username.trim()); byte[] data = getBitmapAsByteArray(picture); if(data != null){ values.put("PICTURE", data); } // 单用户场景:先清空旧数据再插入,避免多条记录 db.delete(TABLE_NAME1, null, null); long id = db.insert(TABLE_NAME1, null, values); db.close(); return id != -1; }
5. 修复读取图片的崩溃问题
读取时先判断Blob是否存在,再解码,避免空指针:
private void getUserInformation(){ Cursor data = databaseHelper.getUserInformation(); if(data != null && data.moveToFirst()) { // 先获取Blob字段,判断是否有效 byte[] blobData = data.getBlob(2); if(blobData != null && blobData.length > 0){ Bitmap bitmap = BitmapFactory.decodeByteArray(blobData, 0, blobData.length); if(bitmap != null) { mCurrentProfileBitmap = bitmap; mProfilePhoto.setImageBitmap(bitmap); } else { // 解码失败,显示默认图 resetToDefaultProfile(); } } else { // 数据库无图片数据,显示默认图 resetToDefaultProfile(); } mProfileName = data.getString(1); } else { // 无用户数据,显示默认状态 resetToDefaultProfile(); mProfileName = ""; } if(data != null){ data.close(); } } // 封装重置默认头像的方法,减少重复代码 private void resetToDefaultProfile(){ mCurrentProfileBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.default_profile_image); mProfilePhoto.setImageBitmap(mCurrentProfileBitmap); }
别忘了确保DatabaseHelper中有正确的查询方法:
// 在DatabaseHelper中添加该方法(如果还没有) public Cursor getUserInformation(){ SQLiteDatabase db = this.getReadableDatabase(); return db.query(TABLE_NAME1, null, null, null, null, null, null); }
额外建议
- SQLite存储Bitmap的局限性:Bitmap转Blob后体积可能较大,频繁读写会影响性能,实际项目中更推荐存储图片的本地文件路径,而非直接存Blob(仅小尺寸头像可考虑Blob)。
- 内存优化:如果用户选择的图片尺寸很大,建议先压缩再存储,避免内存溢出。
内容的提问来源于stack exchange,提问作者JayJona
相关产品推荐
相关产品推荐

