Android使用startActivityForResult回传数据后RecyclerView无法添加用户数据问题
问题解决
错误根因
报错日志中Caused by: java.io.NotSerializableException: android.graphics.Bitmap已明确问题点:你自定义的ModelPerson类实现了Serializable接口用于跨Activity传递,但类中包含的头像字段为Bitmap类型,Bitmap本身未实现Serializable接口,序列化过程直接失败导致崩溃。
另外你当前的ListForNameActivity接收数据后未通知RecyclerView适配器刷新,就算数据传递成功也不会显示在列表中。
推荐解决方案:传递图片Uri + Parcelable替代Serializable
Android跨组件传递数据优先使用Parcelable(性能比Serializable高2-3倍),同时不要直接传递Bitmap,传递图片的本地Uri即可,避免占用过大的Binder缓冲区:
- 重构
ModelPerson类
将头像字段从Bitmap改为Uri类型,同时让ModelPerson实现Parcelable接口,Android Studio可右键类名一键生成Parcelable实现代码。 - 修改LogIn页传递逻辑
无需从ImageView中提取Bitmap,直接使用选图时存储的全局uri变量即可,同时优化返回Intent的写法:
// 删掉原有从ImageView取Bitmap的代码 // profile.buildDrawingCache(); // Bitmap bitmap = profile.getDrawingCache(); // personalInfo.setProfile(bitmap); // 替换为设置Uri personalInfo.setProfile(uri); // 返回Intent无需指定目标类 Intent intent = new Intent(); intent.putExtra("data" , personalInfo); setResult(Activity.RESULT_OK , intent); finish();
- 修改ListForNameActivity接收逻辑
首先将RecyclerView改为类全局变量,接收数据后通知适配器刷新:
public class ListForNameActivity extends AppCompatActivity { FloatingActionButton floatingActionButton; List<ModelPerson> persons; RecyclerView recyclerView; // 改为全局变量 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list_for_name); persons = new ArrayList<>(); recyclerView = findViewById(R.id.mainRecyclerView); // 原有初始化逻辑不变 ... } @Override protected void onActivityResult(int requestCode , int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode , resultCode , data); if (requestCode == RequestCode.ADD_USER_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null){ ModelPerson person = data.getParcelableExtra("data"); persons.add(person); // 通知适配器插入了新数据,刷新列表 recyclerView.getAdapter().notifyItemInserted(persons.size() - 1); } } }
- 列表适配器中拿到Uri后,直接用图片加载库(如Glide)加载到ImageView即可,也可自行通过
MediaStore.Images.Media.getBitmap()转为Bitmap显示。
临时兼容方案:Bitmap转字节数组传递
如果你一定要直接传递Bitmap,可将其压缩为字节数组后再进行序列化:
- 将
ModelPerson中的头像字段改为byte[]类型 - LogIn页设置头像时压缩为字节数组:
profile.buildDrawingCache(); Bitmap bitmap = profile.getDrawingCache(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 压缩质量可自行调整,范围0-100 bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); personalInfo.setProfile(baos.toByteArray());
- 接收数据后转为Bitmap显示:
byte[] profileBytes = person.getProfile(); Bitmap profileBitmap = BitmapFactory.decodeByteArray(profileBytes, 0, profileBytes.length);
注意:该方案仅适合小尺寸头像,图片过大时会触发Binder缓冲区溢出报错
内容的提问来源于stack exchange,提问作者matin
相关产品推荐
相关产品推荐

