Fra*_*cis 5 crash android kotlin android-room kotlin-null-safety
我必须Dao返回简单的对象。如果对象不存在,则Room返回null,但是Android应用程序没有崩溃。另外,如果我将该值分配给非null变量,则应用程序中不会发生崩溃。
道:
@Query("SELECT * FROM users WHERE id LIKE :id LIMIT 1")
abstract fun getById(id: Long): User
Run Code Online (Sandbox Code Playgroud)
不崩溃的代码:
doAsync {
val user: User = userDao.getById(999) // user 999 not exist, userDao returns null
uiThread {
if (user == null) {
Timber.d("user is $user") // "user is null" in log
} else {
Timber.d("user is ${user.email}")
}
}
}
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
这全都涉及Kotlin如何使用Java代码处理边界上的空值。
如果您将Java中的null传递给需要非null值的Kotlin方法,则会获得异常。这是通过调用Intrinsics.checkNotNullKotlin编译器在方法开始时添加的函数来实现的。
例如:
fun hello(who: String): Unit {
println ("Hello $who")
}
Run Code Online (Sandbox Code Playgroud)
变成
public final void hello(@NotNull String who) {
Intrinsics.checkParameterIsNotNull(who, "who");
String var2 = "Hello " + who;
System.out.println(var2);
}
Run Code Online (Sandbox Code Playgroud)
从Kotlin调用Java方法时,添加了类似的检查。
但是如果您有Kotlin接口,它是由Room生成的Java实现。因此Kotlin编译器无法添加检查,因为它无法控制所有接口实现。否则,它将在每次调用Kotlin类或接口之后添加检查,因为它可以用Java实现,这对性能不利。
UPD:在Room bugtracker https://issuetracker.google.com/issues/112323132上发现了类似的问题。Googler表示,这是预期的行为,如果您编写的查询可以返回空值,则您有责任在dao接口中将其标记为可空值。
小智 5
你没有得到 a 的原因NullPointerException很简单:Room 是一个 Java 库,而不是 Kotlin,所以它不知道你User不应该为 null。与 Java 代码交互时,Kotlin 引入了一些 null 检查来给您提供该异常,但由于您的接口是用 Kotlin 编写的,因此它认为这不会成为问题并跳过检查。
我不是 Room 专家,但经过快速谷歌搜索后,我找不到强制 Room 检查空值的方法。我看到解决你的“问题”的两种方法:
getById函数返回值User?@Dao为 Java 接口,强制 Kotlin 检查 null。| 归档时间: |
|
| 查看次数: |
793 次 |
| 最近记录: |