With the configuration below the app is crashing when the @Composable
view calling a ViewModel
opens. Below is the error message as well. I'm not sure if it's the configuration of the database in the ViewModel
. I originally wanted to create an instance of the database in the ViewModel
and pass context
to the ViewModel
but I read that isn't best practice.
ViewModel:
class DataModel(): ViewModel() {
lateinit var database: AppDatabase
fun setDatabase(context: Context) {
database = Room.databaseBuilder(
context,
AppDatabase::class.java, "database"
).build()
}
val data: StateFlow<List<Data>> = flow {
emit(database.dataDao().getAll())
} as StateFlow<List<Data>>
fun addData(data: Data) {
viewModelScope.launch {
database.dataDao().insert(data)
}
}
}
RoomDatabase:
@Database(entities = [Data::class], version = 1)
@TypeConverters(BooleanArrayConverter::class)
abstract class AppDatabase: RoomDatabase() {
abstract fun data(): DataDao
}
@Dao Interface:
@Dao
interface DataDao {
@Query("SELECT * FROM data")
suspend fun getAll(): List<Data>
@Insert
suspend fun insert(vararg data: Data)
}
@Composable View:
fun View(
dataModel: DataModel = viewModel(),
) {
var context = LocalContext.current
Button(
onClick = {
dataModel.setDatabase(context)
},
) {
Text("Button")
}
}
Error:
FATAL EXCEPTION: main
Process: com.example.app, PID: 12733
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:603)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.viewmodel.internal.JvmViewModelProviders.createViewModel(JvmViewModelProviders.kt:38)
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.android.kt:185)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.android.kt:309)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.android.kt:269)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.android.kt:142)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.android.kt:112)
at androidx.lifecycle.viewmodel.ViewModelProviderImpl_androidKt.createViewModel(ViewModelProviderImpl.android.kt:34)
at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release(ViewModelProviderImpl.kt:60)
at androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel_release$default(ViewModelProviderImpl.kt:43)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.android.kt:92)
at androidx.lifecycle.viewmodel.compose.ViewModelKt__ViewModelKt.get(ViewModel.kt:172)
at androidx.lifecycle.viewmodel.compose.ViewModelKt.get(Unknown Source:1)
at androidx.lifecycle.viewmodel.compose.ViewModelKt__ViewModelKt.viewModel(ViewModel.kt:106)
at androidx.lifecycle.viewmodel.compose.ViewModelKt.viewModel(Unknown Source:1)
at com.example.app.View.NewJournalEntrySheet(View.kt:174)
at com.example.app.ComposableSingletons$ViewKt$lambda-1$1.invoke(JournalEntryScreen.kt:45)
at com.example.app.ComposableSingletons$ViewKt$lambda-1$1.invoke(JournalEntryScreen.kt:44)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:130)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.material3.ModalBottomSheetKt$ModalBottomSheetContent$7.invoke(ModalBottomSheet.kt:341)
at androidx.compose.material3.ModalBottomSheetKt$ModalBottomSheetContent$7.invoke(ModalBottomSheet.kt:289)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.material3.SurfaceKt$Surface$1.invoke(Surface.kt:126)
at androidx.compose.material3.SurfaceKt$Surface$1.invoke(Surface.kt:108)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
at androidx.compose.material3.SurfaceKt.Surface-T9BRK9s(Surface.kt:105)
at androidx.compose.material3.ModalBottomSheetKt.ModalBottomSheetContent-IQkwcL4(ModalBottomSheet.kt:218)
at androidx.compose.material3.ModalBottomSheetKt$ModalBottomSheet$3.invoke(ModalBottomSheet.kt:175)
at androidx.compose.material3.ModalBottomSheetKt$ModalBottomSheet$3.invoke(ModalBottomSheet.kt:168)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
2025-07-07 12:19:17.612 12733-12733 AndroidRuntime com.example.peaceofmind E at androidx.compose.material3.ModalBottomSheet_androidKt$ModalBottomSheetDialog$dialog$1$1$1.invoke(ModalBottomSheet.android.kt:300)
at androidx.compose.material3.ModalBottomSheet_androidKt$ModalBottomSheetDialog$dialog$1$1$1.invoke(ModalBottomSheet.android.kt:296)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.material3.ModalBottomSheetDialogLayout.Content(ModalBottomSheet.android.kt:354)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:250)
at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:250)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:216)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:122)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:364)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:140)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$3.invoke(Wrapper.android.kt:139)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:384)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:139)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:123)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:121)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.kt:51)
at androidx.compose.runtime.internal.Utils_jvmKt.invokeComposable(Utils.jvm.kt:27)
at androidx.compose.runtime.ComposerImpl.doCompose-aFTiNEg(Composer.kt:3694)
at androidx.compose.runtime.ComposerImpl.composeContent--ZbOJvo$runtime_release(Composer.kt:3616)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:792)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1132)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4034)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4034)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4034)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:677)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:616)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:123)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114)
at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1963)
2025-07-07 12:19:17.613 12733-12733 AndroidRuntime com.example.app E at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:114)
at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:168)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:313)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:191)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:121)
at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114)
at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:2042)
at android.view.View.dispatchAttachedToWindow(View.java:23105)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3520)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3527)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3527)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3527)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3527)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3618)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3077)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10644)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1570)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1579)
at android.view.Choreographer.doCallbacks(Choreographer.java:1179)
at android.view.Choreographer.doFrame(Choreographer.java:1108)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1553)
at android.os.Handler.handleCallback(Handler.java:995)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loopOnce(Looper.java:248)
at android.os.Looper.loop(Looper.java:338)
at android.app.ActivityThread.main(ActivityThread.java:9067) ... 3 more
Caused by: java.lang.ClassCastException: kotlinx.coroutines.flow.SafeFlow cannot be cast to kotlinx.coroutines.flow.StateFlow
at DataModel.<init>(Data.kt:29)
... 104 more
This casting you are doing here is the problem
val data: StateFlow<List<Data>> = flow {
emit(database.dataDao().getAll())
} as StateFlow<List<Data>>
You cannot cast a Flow
directly to a StateFlow
You can either do this
suspend fun getData() {
data = flow {
emit(database.dataDao().getAll())
}.stateIn(viewModelScope)
}
or a better more typical approach would be
private val _mutableDataFlow: MutableStateFlow<List<Data>> = MutableStateFlow<List<Data>>(mutableListOf())
val data: StateFlow<List<Data>> = _mutableCodeFlow.asStateFlow()
fun getData() {
_mutableDataFlow.value = database.dataDao().getAll()
}