Firebase更新字段后读取失败,触发NullPointerException问题求助
问题描述
尝试读取Firebase Firestore中刚更新的字符串字段office_hours_list时,读取函数返回空字符串,还抛出java.lang.NullPointerException异常(提示null无法转换为非空类型kotlin.String)。
相关代码
读取字段函数
fun readUsersOfficeHoursList(email: String, callback: (String) -> Unit) { val database = FirebaseFirestore.getInstance() val ref = database.collection("Users").document(email) ref.get() .addOnSuccessListener { document -> if (document != null) { val officeHoursList = document.get("office_hours_list") as String callback(officeHoursList) Log.d(TAG, "office_hours_list successfully read") } else { Log.d(TAG, "Is empty") callback("") } } .addOnFailureListener { exception -> if (exception is FirebaseFirestoreException) { Log.e(TAG, "Error getting document: ", exception) } callback("") } }
更新字段函数
fun updateUserOfficeHoursList(email: String, code: String){ val database = FirebaseFirestore.getInstance() val ref = database.collection("Users").document(email) var list = "" ref.get() .addOnSuccessListener { document -> if (document != null) { list = document.get("office_hours_list") as String? ?: "" Log.d(TAG, "office_hours_list successfully read") if(!list.contains(code)){ if (list.isEmpty()){ list = code } else{ list = "$list, $code" } ref.update("office_hours_list", list) .addOnSuccessListener { Log.d(TAG, "List successfully updated") } .addOnFailureListener { e -> Log.w(TAG, "Error updating list", e) } }else{ Log.d(TAG, "code already in the list") } } else { Log.d(TAG, "Is empty") } } .addOnFailureListener { exception -> if (exception is FirebaseFirestoreException) { Log.e(TAG, "Error getting document: ", exception) } } }
测试代码
myClass.updateUserOfficeHoursList("tfh@gmail.com", "1VVNFxSGbYaauk3iLV80, 1a79bhnaJsY5OhHwaYhH") myClass.readUsersOfficeHoursList("tfh@gmail.com") {fieldValue1 -> textView.text = fieldValue1 Log.d(TAG, "fieldValue1: $fieldValue1") }
报错信息
2023-01-16 13:43:50.523 8529-8529/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.myapplication, PID: 8529 java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String at com.example.myapplication.RepositoryMockup$readUsersOfficeHoursList$1.invoke(RespositoryMockup.kt:239) at com.example.myapplication.RepositoryMockup$readUsersOfficeHoursList$1.invoke(RespositoryMockup.kt:237) at com.example.myapplication.RepositoryMockup.readUsersOfficeHoursList$lambda$15(RespositoryMockup.kt:237) at com.example.myapplication.RepositoryMockup.$r8$lambda$Rz1CeV4qQ243JiYTVZ8j2Ijj1y0(Unknown Source:0) at com.example.myapplication.RepositoryMockup$$ExternalSyntheticLambda16.onSuccess(Unknown Source:2) at com.google.android.gms.tasks.zzm.run(com.google.android.gms:play-services-tasks@@18.0.1:1) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7898) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Firestore集合截图
- Users集合:

- OfficeHoursInstance集合:

解决方案
1. 核心问题分析
- 空指针根源:读取函数中
document.get("office_hours_list") as String是强制非空转换,当字段不存在或值为null时,直接抛出异常。 - 异步顺序问题:测试代码中更新和读取并行执行,更新操作还没完成就读取,导致拿到旧数据或null。
2. 修复读取函数
将强制转换改为可空处理,同时用document.exists()替代document != null(Firestore返回的document永远不为null,exists()才是判断文档是否存在的正确方式):
fun readUsersOfficeHoursList(email: String, callback: (String) -> Unit) { val database = FirebaseFirestore.getInstance() val ref = database.collection("Users").document(email) ref.get() .addOnSuccessListener { document -> if (document.exists()) { val officeHoursList = document.get("office_hours_list") as String? ?: "" callback(officeHoursList) Log.d(TAG, "office_hours_list successfully read") } else { Log.d(TAG, "Document does not exist") callback("") } } .addOnFailureListener { exception -> if (exception is FirebaseFirestoreException) { Log.e(TAG, "Error getting document: ", exception) } callback("") } }
3. 修复异步执行顺序
修改更新函数添加完成回调,确保更新成功后再读取:
// 更新函数添加回调参数 fun updateUserOfficeHoursList(email: String, code: String, onComplete: () -> Unit = {}){ val database = FirebaseFirestore.getInstance() val ref = database.collection("Users").document(email) var list = "" ref.get() .addOnSuccessListener { document -> if (document.exists()) { list = document.get("office_hours_list") as String? ?: "" Log.d(TAG, "office_hours_list successfully read") if(!list.contains(code)){ list = if(list.isEmpty()) code else "$list, $code" ref.update("office_hours_list", list) .addOnSuccessListener { Log.d(TAG, "List successfully updated") onComplete() } .addOnFailureListener { e -> Log.w(TAG, "Error updating list", e) onComplete() } }else{ Log.d(TAG, "code already in the list") onComplete() } } else { Log.d(TAG, "Document does not exist") onComplete() } } .addOnFailureListener { exception -> if (exception is FirebaseFirestoreException) { Log.e(TAG, "Error getting document: ", exception) } onComplete() } } // 测试代码调整为更新完成后读取 myClass.updateUserOfficeHoursList("tfh@gmail.com", "1VVNFxSGbYaauk3iLV80, 1a79bhnaJsY5OhHwaYhH") { myClass.readUsersOfficeHoursList("tfh@gmail.com") { fieldValue1 -> textView.text = fieldValue1 Log.d(TAG, "fieldValue1: $fieldValue1") } }
4. 额外优化建议
- 不要用字符串拼接存储列表,Firestore支持直接存储
List<String>类型,用FieldValue.arrayUnion()可以自动去重添加元素,代码更简洁高效。 - 统一使用
document.exists()判断文档是否存在,避免逻辑混淆。
内容的提问来源于stack exchange,提问作者real4you
相关产品推荐
相关产品推荐

