我想我已经知道我需要在onSaveInstanceState
的某个地方保存一些东西,但是我不知道是什么以及如何保存。我猜它与数据库有关,因为错误中提到了房间。
我的应用程序使用NavGraph
来Map屏幕,所以我不知道我是否应该逐个保存所有的Fragment
,或者我可以使用一些NavGraph
相关的解决方案。对于ViewModel
s,我已经使用了类似的东西:
private val actDevInfVM: ActuatorDeviceInfoViewModel by viewModels {
ActuatorDeviceInfoViewModel.ActuatorDeviceInfoViewModelFactory((ctx.application as MyApp).actuatorDeviceInfoRepo)
}
要在Fragment
或Activity
上加载ViewModel
s,我尝试将其替换为:
private val actDevInfVM: ActuatorDeviceInfoViewModel by navGraphViewModels(R.id.main_nav_graph) {
defaultViewModelProviderFactory
}
但我得到了一组不同的错误,但对于另一个ViewModel
似乎。我得到一个错误,看起来像:
无法创建类com.my.package.name.viewmodel.SensorViewModel的示例
我的ViewModel
s看起来像:
class ActuatorDeviceInfoViewModel(private val repo: ActuatorDeviceInfoRepo) : ViewModel(),
IViewModel<ActuatorDeviceInfo> {
private val _items = MutableStateFlow<List<ActuatorDeviceInfo>>(listOf())
override val items: StateFlow<List<ActuatorDeviceInfo>> = _items
fun fetchAll() {
viewModelScope.launch(Dispatchers.Main) {
repo.getAllSub
.flowOn(Dispatchers.IO)
.catch { exception -> exception.localizedMessage?.let { Log.e("TAG", it) } }
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
.collect { _items.value = it }
}
}
fun getAll(): StateFlow<List<ActuatorDeviceInfo>> {
return _items
}
fun getAllLst(): List<ActuatorDeviceInfo> {
return repo.getAllLst()
}
fun getAllWithEdgeDeviceId(edgeDeviceId: String): List<ActuatorDeviceInfo> {
return runBlocking {
repo.getAllWithEdgeDeviceId(edgeDeviceId)
}
}
fun insert(item: ActuatorDeviceInfo) = viewModelScope.launch {
repo.insert(item)
}
override fun insertReturnId(item: ActuatorDeviceInfo): Long {
return runBlocking {
repo.insertReturnId(item)
}
}
override fun update(item: ActuatorDeviceInfo) = viewModelScope.launch {
repo.update(item)
}
override fun insertOrUpdate(item: ActuatorDeviceInfo) = viewModelScope.launch {
repo.insertOrUpdate(item)
}
fun delete(item: ActuatorDeviceInfo) = viewModelScope.launch {
repo.delete(item)
}
class ActuatorDeviceInfoViewModelFactory(private val repo: ActuatorDeviceInfoRepo) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(ActuatorDeviceInfoViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return ActuatorDeviceInfoViewModel(repo) as T
}
throw IllegalArgumentException("Unknown VieModel Class")
}
}
companion object {
const val TAG = "ActuatorDeviceInfoViewModel"
}
}
然后在MyApp
上,我有这样的代码:
class MyApp : Application() {
private val applicationScope = CoroutineScope(SupervisorJob())
val actuatorDeviceInfoRepo by lazy { ActuatorDeviceInfoRepo(database.actuatorDeviceInfoDao()) }
val sensorRepo by lazy { SensorRepo(database.sensorDao()) }
...
fun dbClose() {
database.close()
}
}
dbClose()
在MainActivity
s onDestroy()
上调用
下面是AppDatabase
的样子:
@Database(
entities = [
ActuatorDeviceInfo::class,
Sensor::class,
... a few more data classes ...
], version = 1, exportSchema = false
)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun actuatorDeviceInfoDao(): ActuatorDeviceInfoDao
abstract fun sensorDao(): SensorDao
... a few more dao ...
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context, scope: CoroutineScope): AppDatabase {
val queryInterceptor = LoggingQueryInterceptor()
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"some_db_name"
)
.addCallback(AppDbCallback(scope))
.setQueryCallback(queryInterceptor, Executors.newSingleThreadExecutor())
.build()
INSTANCE = instance
instance
}
}
}
}
2条答案
按热度按时间w6lpcovy1#
不确定这是否回答了你的问题,但为了避免屏幕旋转时重新加载活动,请在清单中添加以下内容:
要在屏幕方向更改时执行某些操作,请执行以下操作:
r6hnlfcb2#
dbClose()
在MainActivitysonDestroy()
上调用所以,你让
no such table: room_table_modification_log
旋转的原因是因为onDestroy()
生命周期回调在设备方向改变时被系统触发;这意味着每次方向改变,数据库都将关闭,这将是很麻烦的,因为:Room
)。查看1和2问题。因此,根据您的情况推荐一种:
isFinishing()
的设备定向情况区别开来,例如: