应用程序轮换时收到“没有这样的表:room_table_modification_log”

问题描述 投票:0回答:1

我想我已经发现我需要在 onSaveInstanceState 的某个地方保存一些东西,但我不知道什么以及如何保存。我猜这与数据库有关,因为错误中提到了 room。

我的应用程序正在使用 NavGraph 来映射屏幕,所以我不知道是否应该一一保存我的所有

Fragment
,或者有一些我可以使用的
NavGraph
相关解决方案。对于
ViewModel
,我已经使用了类似的东西:

private val actDevInfVM: ActuatorDeviceInfoViewModel by viewModels {
    ActuatorDeviceInfoViewModel.ActuatorDeviceInfoViewModelFactory((ctx.application as MyApp).actuatorDeviceInfoRepo)
}

ViewModel
加载到
Fragment
Activity
上。我尝试将其替换为:

private val actDevInfVM: ActuatorDeviceInfoViewModel by navGraphViewModels(R.id.main_nav_graph) {
    defaultViewModelProviderFactory
}

但是我遇到了一组不同的错误,但对于另一个

ViewModel
来说似乎是这样。我收到如下错误:

无法创建类的实例 com.my.package.name.viewmodel.SensorViewModel

我的

ViewModel
看起来像:

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
            }
        }
    }
}
android kotlin android-room android-viewmodel
1个回答
0
投票

不确定这是否回答了您的问题,但为了避免屏幕旋转时重新加载活动,请在清单中添加以下内容:

<activity>
(your activity)
android:configChanges="keyboardHidden|orientation|screenSize">
</activity>

当屏幕方向改变时执行某些操作:

@Override public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    Toast.makeText(this, "config changed", Toast.LENGTH_SHORT).show();

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    } }
© www.soinside.com 2019 - 2024. All rights reserved.