what is the correct way or what is the difference in using flow in composable

62 Views Asked by At
In my viemodel I get from my RoomDB  a list of SmthObjects as StateFlow<List<SmthObject>>.

In my composable I use that list:

val listVM = viewmodel<MyViewModel>()
//var 1
val listVM = listVM.smthObjects.collectAsState()
val list = remember{
       **listVM**
}

and next I use this list in LazyColumn

but I cant do :

//var 2
val list = remember{
      **mutableStateOf(listVM.smthObjects)**
}

and use list as list.value.collectAsState().value

What is the correct way?

2

There are 2 best solutions below

7
TheLibrarian On BEST ANSWER

Sometimes doing Google's Codelabs is worth the time it takes.

@Composable
fun GameScreen(
   gameViewModel: GameViewModel = viewModel()
) {
   // ...
}

Use by(delegate) and you don't have to call .value

val gameUiState by gameViewModel.uiState.collectAsState()

In your case something like this:

val listVM = viewmodel<MyViewModel>()
val smthObjects by listVM.smthObjects.collectAsState()

LazyColumn {
    items(smthObjects) { smthObject ->
        // Your UI for the object
    }
}

Also, you don't want to hoist the state of the directly in the composable but in the view model itself.

class MyViewModel(private val roomDB: RoomDB): ViewModel() {

    val smthObjects: StateFlow<List<SmthObject>> = roomDB.loadSmthObjects()
        .stateIn(
            scope = viewModelScope, 
            started = SharingStarted.WhileSubscribed(5_000), 
            initialValue = emptyList()
        )
}
0
Hezy Ziv On

Use collectAsState() Directly in Composable:

@Composable

fun YourComposable() {
    val viewModel: MyViewModel = viewModel() // Get ViewModel

    // Collect the StateFlow as State
    val list = viewModel.smthObjects.collectAsState().value

    // Use the list in LazyColumn
    LazyColumn {
        items(list) { item ->
            // Display each item
        }
    }
}