I have a Jetpack Compose (desktop) app with a database, and I want to show some UI based on data from the db:
val data = remember { mutableStateListOf<Dto>() }
Column {
data.forEach { /* make UI */ }
}
My question is, at which point should I execute my database query to fill the list?
I could do
val data = remember { mutableStateListOf<Dto>() }
if (data.isEmpty()) data.addAll(database.queryDtos())
The isEmpty
check is needed to prevent requerying on re-compose, so this is obviously not the way to go.
Another option would be
val data = remember {
val state = mutableStateListOf<Dto>()
state.addAll(database.queryDtos())
state
}
This way I can't reuse a database connection, since it's scoped inside the remember block. And queries should probably happen async, not inside this initializer
So, how to do this nicely?
In Android the cleanest way is using view model, and call such code in
init
.In Desktop it depends on the operation. The main benefit of this platform is that there's no such thing as Android configuration change, so
remember
/LaunchedEffect
are not gonna be re-created.If the initialization code is not heavy, you can run it right inside
remember
.In case you need to update the list later, add
.toMutableStateList()
If it's something heavy, it's better to go for
LaunchedEffect
. It will have the same lifecycle asremember
- run the containing code only the first time the view appears: