Home > Software engineering >  How to nicely init state from database in Jetpack Compose?
How to nicely init state from database in Jetpack Compose?

Time:04-07

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?

CodePudding user response:

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.

  1. If the initialization code is not heavy, you can run it right inside remember.

    val data = remember { database.queryDtos() }
    

    In case you need to update the list later, add .toMutableStateList()

  2. If it's something heavy, it's better to go for LaunchedEffect. It will have the same lifecycle as remember - run the containing code only the first time the view appears:

    val data = remember { mutableStateListOf<Dto>() }
    LaunchedEffect(Unit) {
        data.addAll(database.queryDtos())
    }
    
  • Related