You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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集合:Users Collection
  • OfficeHoursInstance集合:OfficeHoursInstanceCollection

解决方案

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:10:32