Hello, how do i make this idea work : api.stream i...
# compose
f
Hello, how do i make this idea work : api.stream is reading a websocket, the idea is to update a variable every time it receives a websocket message.
s
You can use a lambda:
Copy code
suspend fun updateState(api: Api, onRecieve: (String) -> Unit) {
    val notify =  Channel<String>()
    api.stream(notify)
    while(true) {
        onRecieve(notify.receive())
    }
}  

@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun SomeComposable(api: Api, locationViewModel: LocationViewModel = viewModel()) {
    var state by remember { mutableStateOf("") }
    val composableScope = rememberCoroutineScope()
    composableScope.launch {
        updateState(api, onRecieve = { state = it })
    }
}
f
This makes the api.stream goes on some loop and connect multiple times instead of one time and just reading
s
Oh yeah you need
LaunchedEffect
f
What is this ?
f
What do i use as a key?
Oh, get it
s
I guess you can use your api as the key since it will relaunch when your api changes
Also, shouldn't the
updateState
be in your view model?
f
Any idea why it prints "" then the real state value ?
s
Because the initial value of your state is an empty string
f
Any way to the variable only holds the newer value ?
I'm using the view model to store some coordinates that changes when the user click on a map
s
You can make the state null initially or maybe use a flow
You can make another view model for your api stuff if you don't want it in the location view model
f
So a viewModel is better than a simple remember in this case?
s
From what I'm seeing, yes. It's always better to keep the UI separate
d
Should probably be
fun updateState(api: Api): Flow<String>
that returns a
channelFlow { .... }
. Then you can use
collectAsState()
.
f
What would be a snippet of this ? i never used a channelFlow before
d
Copy code
fun updateState(api: Api): Flow<String> {
    return channelFlow<String> {
        api.stream(this)
        awaitClose { /* do closing things if needed */ }
    }
}
Copy code
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun SomeComposable(api: Api, locationViewModel: LocationViewModel = viewModel()) {
    val state by remember(api) { updateState(api) }.collectAsState("")
    // do stuff with state
}
f
I saw here that it is a experimental api, is this safe to use ?
d
It was stabilised in the latest release so don't worry about it.
f
Ok, thank you all !
👍 1