Firebase文本与图片上传触发应用崩溃问题求助
解决Firebase上传时的NullPointerException问题
错误根源分析
从Logcat日志可以明确看到,空指针异常出现在uploadPicture方法的imgPath.putFile(uri)这一行,核心原因是:你声明了成员变量imgPath但从未给它赋值,它始终处于null状态。
更关键的是,你在setProfilePicture和setCoverPicture方法里已经正确创建了StorageReference实例,并把它作为参数传给了uploadPicture,但uploadPicture方法完全没用到这个传入的参数,反而去调用了未初始化的imgPath,这直接触发了空指针崩溃。
第一步:修复空指针问题
修改uploadPicture方法,把方法内的imgPath替换成传入的storageReference参数,同时可以删掉多余的imgPath成员变量,避免后续混淆:
public class ProfileUtils { private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance(); private FirebaseAuth firebaseAuth; private StorageReference storageReference; private Map<String, String> userSetupMap; private ProcessStatusObservable processStatusObservable; // 移除多余的imgPath成员变量 private String userId; public ProfileUtils(){ processStatusObservable = new ProcessStatusObservable(); userSetupMap = new HashMap<>(); firebaseAuth = FirebaseAuth.getInstance(); userId = firebaseAuth.getCurrentUser().getUid(); storageReference = FirebaseStorage.getInstance().getReference(); } private void uploadPicture(String pictureType, Uri uri, StorageReference storageReference){ // 使用传入的storageReference而非未初始化的imgPath storageReference.putFile(uri).addOnCompleteListener(task -> { if(task.isSuccessful()){ Uri imageUri = task.getResult().getDownloadUrl(); userSetupMap.put(pictureType.concat("PictureUrl"), imageUri.toString()); } else{ // 建议添加错误处理,通知观察者上传失败 processStatusObservable.setStatus(ProcessStatus.NEW_USER_PROFILE_SETUP_FAILED); } }); } // 其余方法保持不变... }
第二步:解决异步上传的时序问题
修复空指针后,还有一个潜在的隐性问题:图片上传是异步操作,如果你直接调用commit(),Firestore的写入可能会先执行,此时图片URL还没被存入userSetupMap,导致用户资料缺少图片地址。
可以通过Firebase的Tasks.whenAll()方法等待所有上传任务完成后,再执行Firestore的写入操作:
public class ProfileUtils { // 添加成员变量保存所有上传任务 private List<Task<UploadTask.TaskSnapshot>> uploadTasks = new ArrayList<>(); // ...其他成员变量 private void uploadPicture(String pictureType, Uri uri, StorageReference storageReference){ Task<UploadTask.TaskSnapshot> uploadTask = storageReference.putFile(uri).addOnCompleteListener(task -> { if(task.isSuccessful()){ Uri imageUri = task.getResult().getDownloadUrl(); userSetupMap.put(pictureType.concat("PictureUrl"), imageUri.toString()); } else{ processStatusObservable.setStatus(ProcessStatus.NEW_USER_PROFILE_SETUP_FAILED); } }); // 将当前上传任务加入列表 uploadTasks.add(uploadTask); } public void commit(){ // 等待所有上传任务完成后再执行Firestore写入 Tasks.whenAll(uploadTasks).addOnCompleteListener(uploadBatchTask -> { if(uploadBatchTask.isSuccessful()){ firebaseFirestore.collection("Users").document(userId) .set(userSetupMap).addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if(task.isSuccessful()){ processStatusObservable.setStatus(ProcessStatus.NEW_USER_PROFILE_SETUP_SUCCESS); } else{ processStatusObservable.setStatus(ProcessStatus.NEW_USER_PROFILE_SETUP_FAILED); } } }); } else{ processStatusObservable.setStatus(ProcessStatus.NEW_USER_PROFILE_SETUP_FAILED); } }); } }
这样就能确保所有图片上传完成并获取到下载URL后,再把完整的用户资料写入Firestore,避免数据不完整的问题。
内容的提问来源于stack exchange,提问作者Sachin Titus
相关产品推荐
相关产品推荐

