Android聊天应用Cloud Firestore数据写入失败问题排查
Android聊天应用Cloud Firestore数据写入失败问题修复
问题现象
开发Android聊天应用时,已编写用户资料保存代码,但Cloud Firestore中无对应Users集合数据,导致RecyclerView无法从Firestore拉取用户列表完成渲染。
核心原因
代码存在异步流程时序错误,是导致数据无法写入的根因:
- 保存按钮点击逻辑中,调用
sendDataForNewUser()后立刻执行页面跳转并finish当前Activity,但图片上传到Storage、获取图片下载URI、写入Firestore全是异步回调操作,此时Activity被销毁,异步任务被系统终止,根本执行不到Firestore写入逻辑。 - Firestore写入、图片上传、URI获取等操作均未添加失败回调,发生权限错误、网络错误、空指针异常时无任何提示,无法感知失败原因。
- 图片解码逻辑未做空判断,一旦图片读取失败触发空指针,会直接中断整个保存流程。
修复方案
- 调整页面跳转时机:移除保存按钮点击事件中立即跳转、关闭页面的逻辑,等所有异步流程(实时库写入、图片上传、Firestore写入)全部执行成功后,再执行页面跳转。
- 补全所有异步操作的失败回调:为每个Firebase异步任务添加失败监听,弹出错误提示方便定位问题,出错时及时关闭加载进度条避免卡死。
- 增加空值容错判断:图片解码后增加bitmap空校验,避免空指针崩溃中断流程。
修复后核心代码
保存按钮点击逻辑
msaveprofile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { name = mgetusername.getText().toString(); if(name.isEmpty()){ Toast.makeText(getApplicationContext(), "Name is Empty", Toast.LENGTH_SHORT).show(); } else if(imagepath == null){ Toast.makeText(getApplicationContext(), "Image is Empty", Toast.LENGTH_SHORT).show(); } else { mprogressbarofsetprofile.setVisibility(View.VISIBLE); sendDataForNewUser(); // 移除此处的立即跳转、finish、进度条隐藏逻辑,等所有异步完成后再执行 } } });
图片上传方法
private void sendImagetoStorage() { StorageReference imageref = storageReference.child("Images").child(firebaseAuth.getUid()).child("Profile Pic"); Bitmap bitmap = null; try { bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imagepath); } catch (IOException e) { e.printStackTrace(); mprogressbarofsetprofile.setVisibility(View.INVISIBLE); Toast.makeText(getApplicationContext(), "Failed to read image", Toast.LENGTH_SHORT).show(); return; } // 新增bitmap空判断 if (bitmap == null) { mprogressbarofsetprofile.setVisibility(View.INVISIBLE); Toast.makeText(getApplicationContext(), "Failed to parse image", Toast.LENGTH_SHORT).show(); return; } ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 25, byteArrayOutputStream); byte[] data = byteArrayOutputStream.toByteArray(); UploadTask uploadTask = imageref.putBytes(data); uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { imageref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri uri) { ImageUriAcessToken = uri.toString(); Toast.makeText(getApplicationContext(), "URI get Success", Toast.LENGTH_SHORT).show(); sendDataTocloudFireStore(); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { mprogressbarofsetprofile.setVisibility(View.INVISIBLE); Toast.makeText(getApplicationContext(), "URI get Failed: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } }); Toast.makeText(getApplicationContext(), "Image is uploaded", Toast.LENGTH_SHORT).show(); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { mprogressbarofsetprofile.setVisibility(View.INVISIBLE); Toast.makeText(getApplicationContext(), "Image upload Failed: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
Firestore写入方法
private void sendDataTocloudFireStore() { DocumentReference documentReference = firebaseFirestore.collection("Users").document(firebaseAuth.getUid()); Map<String, Object> userdata = new HashMap<>(); userdata.put("name", name); userdata.put("image", ImageUriAcessToken); userdata.put("uid", firebaseAuth.getUid()); userdata.put("status", "Online"); documentReference.set(userdata) .addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { mprogressbarofsetprofile.setVisibility(View.INVISIBLE); Toast.makeText(getApplicationContext(), "User profile set Successfully", Toast.LENGTH_SHORT).show(); // 所有流程执行成功后再跳转页面 Intent intent = new Intent(ControlDesk.this, Chat.class); startActivity(intent); finish(); } }) // 新增失败回调 .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { mprogressbarofsetprofile.setVisibility(View.INVISIBLE); Toast.makeText(getApplicationContext(), "Firestore write Failed: " + e.getMessage(), Toast.LENGTH_LONG).show(); } }); }
额外配置检查
确认Firebase控制台Firestore安全规则配置正确,测试阶段可使用如下规则允许已登录用户写入自己的资料:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /Users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; } } }
内容的提问来源于stack exchange,提问作者Ayesha Anwer
相关产品推荐
相关产品推荐

