我有Dao
返回简单对象。如果对象不存在,Room返回null
,但Android应用程序没有崩溃。另外,如果我将该值分配给非null变量,则应用程序中不会发生崩溃。
道:
@Query("SELECT * FROM users WHERE id LIKE :id LIMIT 1")
abstract fun getById(id: Long): User
不崩溃代码:
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}")
}
}
}
我有两个问题:
答案 0 :(得分:4)
关于Kotlin如何处理Java代码边界上的空值。
如果您将Java中的null传递给需要非null值的Kotlin方法,则会获得异常。这可以通过调用Kotlin编译器在方法开始时添加的Intrinsics.checkNotNull
函数来实现。
例如:
fun hello(who: String): Unit {
println ("Hello $who")
}
成为
public final void hello(@NotNull String who) {
Intrinsics.checkParameterIsNotNull(who, "who");
String var2 = "Hello " + who;
System.out.println(var2);
}
从Kotlin调用Java方法时添加了类似的检查。
但是,在这种情况下,您具有Kotlin接口,它是由Room生成的Java实现。 因此Kotlin编译器无法添加检查,因为它无法控制所有接口实现。否则,每次调用Kotlin类或接口后,都必须添加检查,因为它可以用Java实现,这对性能不利。
UPD:在Room Bugtracker https://issuetracker.google.com/issues/112323132发现了类似的问题。 Googler说这是有意的行为,如果您编写的查询可以返回空值,那么您有责任在dao接口中将其标记为可空。
答案 1 :(得分:1)
据我了解,您生成的Dao类并未将返回值注释为Java代码中的@Nullable。
@Override
public User getById(long id) {
应该是
@Override
public @Nullable User getById(long id) {
因此您看不到警告
答案 2 :(得分:1)
您没有得到NullPointerException
的原因很简单:Room是Java库而不是Kotlin,因此不知道您的User
不应为null。
当与Java代码进行交互时,Kotlin引入了一些空检查来为您提供该异常,但是由于您的界面是用Kotlin编写的,因此它假定这不会出现问题,并且会跳过该检查。
我不是会议室专家,但是经过Google的快速搜索之后,我找不到强迫会议室检查空值的方法。我看到两种解决您的“问题”的方法:
getById
函数以返回User?
@Dao
转换为Java接口,迫使Kotlin检查是否为空。