由于我不能成功地预制migration,我决定继续使用新的数据库.我在当前版本的应用程序中有一个名为Cars.db
的数据库,在新版本中,应用程序将创建一个名为MyCars.db
的新数据库,并将Cars.db
中的数据插入到新的数据库中.
以下是一种解决方法,我是如何做到的:
class MainActivity : ComponentActivity() {
private lateinit var data: Data
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
data = ViewModelProvider(this)[Data::class.java]
setContent {
.....
AppTheme {
.....
}
LaunchedEffect(key1 = Unit) {
data.onMigrate() //-> Start migration
}
}
}
}
我的AndroidViewModel
个班级:
class Data(private val application: Application) : AndroidViewModel(application) {
....
fun onMigrate() {
try {
val path = application.getDatabasePath("Cars.db") // will this work for all os versions >= 26 sdk?
val database = SQLiteDatabase.openDatabase(path.path, null, SQLiteDatabase.OPEN_READONLY)
val cursor = database.query("Cars", null, null, null, null, null, null)
val carsList = ArrayList<Car>(cursor.count)
while (cursor.moveToNext()) {
val timestamp = try {
cursor.onStringColumn("Modified").toLong()
} catch (_: Exception) {
currentTime
}
val color = cursor.getString(cursor.getColumnIndexOrThrow("Color")) ?: null
carsList.add(
Car(
color = color,
timestamp = timestamp,
model = cursor.onStringColumn("Model"),
manufacture = cursor.onStringColumn("Manufacture"),
labels = cursor.onStringColumn("Tags").stringToList() // stringToList() is a custom extension of String.
)
)
}
if (carsList.isNotEmpty()) {
onScope {
carsRepo.insert(carsList)
delay(20) // -> Wait 20 ms
application.deleteDatabase("Cars.db") // delete the "Cars.db"
}
}
cursor.close()
} catch (_: Exception) {
}
}
....
}
然而,我不确定是否能获得旧数据库的路径.既然有许多不同制造商的不同设备,这val path = application.getDatabasePath("Cars.db")
能在每个Android操作系统版本>;=sdk 26上运行以获取旧数据库的路径吗?
另一个问题是,无论official方式如何,这种迁移是否足够好?