I have a view model that gets search query data string every time a user enter a text in my text field in the Top App Bar.
The view model is as follows:
ViewModel.kt
class ServicesViewModel(
private val offlineServiceRepository:ServiceRepository
) : ViewModel() {
private var searchQuery = mutableStateOf("")
val servicesUiState: StateFlow<ServicesUiState> = offlineServiceRepository.search(searchQuery.value).map {
Log.i("SEARCHVALUE", "UPDATE SF: ${searchQuery.value}")
ServicesUiState.Success(it)
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS),
initialValue = ServicesUiState.Loading
)
fun updateSearchQuery(query: String){
searchQuery.value = query
Log.i("SEARCHVALUE", "SQ: ${searchQuery.value}")
}
Then in my screen:
@Composable
fun ScreenServices(
viewModel: ServicesViewModel,
retryAction: () -> Unit,
navigateToPreCall: (service: Service) -> Unit,
searchBarValue: String,
modifier: Modifier = Modifier
) {
val servicesUiState by viewModel.servicesUiState.collectAsState()
viewModel.updateSearchQuery(searchBarValue)
when (servicesUiState) {
is ServicesUiState.Loading -> LoadingScreen(modifier)
is ServicesUiState.Success -> ServicesList((servicesUiState as ServicesUiState.Success).services, navigateToPreCall, modifier)
is ServicesUiState.Error -> ErrorScreen(retryAction, modifier)
}
}
The searchBarValue
is being sent successfully from my UI screen to the viewModel every time the user types a new text and the searchQuery
variable is updated accordingly. However the servicesUiState
isn't getting the updated searchQuery.value
and hence the list is not being updated on my UI.
Can someone help out on how i can pass the searchQuery
variable to my servicesUiState
StateFlow
variable in my view model ?
(Mutable)State
is a value holder class that could be observed for changes and comes with jetpack compose. It is similar to kotlin Flow
. When you use it in a @Composable
function, it will be automatically observed and your @Composable
function will be recomposed on every change. You are not using it in a composable function, so you have to observe it yourself. One way to do that would be using snapshotFlow
function to convert it to Flow
:
private val searchQueryFlow = snapshotFlow { searchQuery.value }
val serviceUiState = searchQueryFlow.map { query ->
offlineServiceRepository.search(query)
}.map { ... }
In your case though, it will be better to use MutableStateFlow
instead, using MutableState
here doesn't make much sense.