【问题标题】:How to avoid KotlinNullPointerException when creating a new User object?创建新的 User 对象时如何避免 KotlinNullPointerException?
【发布时间】:2020-09-28 17:50:24
【问题描述】:

我在 Firebase 中有这个验证码:

auth.signInWithCredential(credential).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val firebaseUser = auth.currentUser!!
        val user = User(firebaseUser.uid, firebaseUser.displayName!!) //KotlinNullPointerException
    } 
}

这是我的用户类:

data class User constructor(var uid: String? = null): Serializable {
    var name: String? = null

    constructor(uid: String, name: String) : this(uid) {
        this.name = name
    }
}

我在突出显示的行上得到一个KotlinNullPointerException。构造函数的调用怎么会产生这个异常呢?如何避免?

【问题讨论】:

  • 我认为由于 name 是可选变量,只需像使用 uid 一样将其放入主构造函数中,不要使用 !! 运算符。喜欢User(var uid: String? = null, var name: String? = null)
  • @AnimeshSahu 谢谢,但我需要这种方式。
  • this way哪个方向?
  • @AnimeshSahu 我需要一个带有一个参数的构造函数以及一个带有两个参数的构造函数。
  • 带有可选参数的构造函数在编译时生成重载构造函数,同理。你也可以像User("my-id") 这样称呼它。

标签: android firebase kotlin firebase-authentication kotlin-null-safety


【解决方案1】:

只需像这样声明你的类:

data class User(var uid: String? = null, var name: String? = null) : Serializable

然后你可以这样称呼它:

auth.signInWithCredential(credential).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        auth.currentUser?.apply {  // safe call operator, calls given block when currentUser is not null
            val user = User(uid, displayName)
        }
    } 
}

可以像这样创建用户实例:

User() // defaults to null as specified
User("id") // only id is set, name is null
User(name = "test-name") // only name is set id is null

= null 完全允许调用可选地传递参数,当不传递时默认为 null

编辑:正如@GastónSaillén 所建议的,您应该在 Android 中使用 Parcelable。

@Parcelize
data class User(var uid: String? = null, var name: String? = null) : Parcelable

【讨论】:

  • 你的意思是val user = User(auth.currentUser.uid, auth.currentUser.displayName)
  • @LisDya apply 块将 auth.currentUser 作为 lambda 中的 this 变量传递,因此 uid 隐式调用 this.uid 隐式调用 auth.currentUser
  • 我会使用 Parcelable 而不是 Serializable 因为对于 Android 来说比 Serializable 接口更好
  • 我完全按照你说的做了,但是当我打电话给val user = User(uid = "test-uid", name = "test-name") 时,我仍然得到KotlinNullPointerException。应该做点别的吗?
  • @LisDya 我真的不明白你是怎么得到它的,stacktrace 是否正好指向这一行?必须有一个非空的安全调用 !! 从那里抛出 KotlinNullPointerException。
【解决方案2】:

您可以像这样在 Kotlin 中处理可为空的字段:

val user = auth.currentUser?.let { firebaseUser -> 
   firebaseUser.displayName?.let { displayName -> 
      User(firebaseUser.uid,  displayName)
   }
}

操作员!! 非常危险,在大多数情况下应该避免

【讨论】:

  • 如果我有另一个论点firebaseUser.email,我该如何解决这个问题?
  • 在这种情况下,您可以在firebaseUser 上再添加一个内部let {} 函数调用。它看起来与displayName 处理相同
猜你喜欢
  • 1970-01-01
  • 2016-11-29
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多