我非常了解Kotlin空安全性。我知道 ”?” 在类型(例如:Int?)之后可以用来将变量或值声明为可为空。我也知道!运算符用于返回非空值或引发NPE。
通常,带有“?”的类型 之后将为空,并且不带“?” 是非null。但是当我检查一些类似这样的变量时,我已经看到:
var myVariable:整数!
当您使用Kotlin代码中的Java代码时,就会发生这种情况。
//java code
public class Foo {
public Integer calcNumber()
{
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用函数Foo.calcNumber()
//kotlin code
val meh = Foo().calcNumber()
print(meh)
Run Code Online (Sandbox Code Playgroud)
值meh被检查为Int !,而不是Int或Int?。显然,此处的值meh可以为null,但“ IDE”无法正确“检测”。
如
var a: Int! = 10
Run Code Online (Sandbox Code Playgroud)
是无效的,我的问题是:带“!”的类型到底是什么意思?
我在 Room 数据库生成器中添加了一个复杂的迁移。由于此特定迁移需要从服务器下载一些数据,因此我使用启动屏幕等待整个过程完成,然后再打开应用程序的主要活动。
问题是迁移不会在“build()”方法上自动执行,因为它们似乎是在单独的线程上内部执行的。
我还考虑过使用 RoomDatabase.Callback 来检测数据库何时打开,但由于迁移很复杂并且尝试从服务器下载数据,它可能会失败,并且应用程序可能会永远等待。
我需要触发迁移并等待其完成,如果可能的话捕获迁移错误。
这是应用程序类上的代码:
appLoadingStatus.value = AppLoadingStatus.INITIALIZING
db= Room.databaseBuilder(this@App,Database::class.java,"app-database")
.addMigrations(Database.MIGRATION_12_13).build()
//Here I need to wait for migrations to finish in case they are executed, and catch ay possible errors
appLoadingStatus.value = AppLoadingStatus.INITIALIZED
Run Code Online (Sandbox Code Playgroud)
这就是迁移:
val MIGRATION_12_13: Migration = object : Migration(12, 13) {
override fun migrate(database: SupportSQLiteDatabase) {
runBlocking(Dispatchers.Main) {
val newIds =App.instance.getIdsForMigration()?:throw IllegalStateException("Unable do get data from server")
database.execSQL("ALTER TABLE Coin ADD `id` INTEGER NOT NULL")
newIds.forEach {symbolIdPair->
database.execSQL("UPDATE Coin SET id='${symbolIdPair.id}' where symbol='${symbolIdPair.symbol}'")
} …
Run Code Online (Sandbox Code Playgroud)