Pablo
06/08/2024, 6:58 AMviewmodel
with Flow
and Room
that connected my variables on the UiState
with Room
using .first()
as the codelabs showed me. I noticed that using .first()
is not a good idea because when I inserted something in the database, the screen didn't get refreshed automatically showing the new value. So I learned that using collect{}
is the correct approach to continuously update the uistate variables automatically. After changing it now my screen is not showing any data and I can't disscover why. Please, can you help me trying to find where is the issue? I'm adding the viewmodel here.Pablo
06/08/2024, 6:59 AMdata class UiState(
val searchResult: List<Airport> = listOf(),
val favorites: List<Favorite> = listOf(),
val selectedAirport: Airport? = null,
val flightsForSelectedAirport: List<Airport> = listOf()
)
class FlightsScreenViewModel(
private val flightRepository: FlightsRepository,
private val userPreferencesRepository: UserPreferencesRepository
) : ViewModel() {
var uiState by mutableStateOf(UiState())
private set
var searchText by mutableStateOf("")
private set
init {
viewModelScope.launch {
// searchText = userPreferencesRepository.searchText.first()
userPreferencesRepository.searchText.collect{ searchText = it }
updateSearchResults()
}
}
private suspend fun updateSearchResults() {
// val searchResult = if (searchText != "")
// flightRepository.getAirportsByIatOrName(searchText).filterNotNull().first()
// else
// emptyList()
//
// val favorites = flightRepository.getFavorites().filterNotNull().first()
//
// uiState = uiState.copy(
// searchResult = searchResult,
// favorites = favorites
// )
if (searchText != "") {
flightRepository.getAirportsByIatOrName(searchText).filterNotNull().collect{ uiState = uiState.copy(searchResult = it) }
} else {
uiState = uiState.copy(favorites = emptyList())
}
flightRepository.getFavorites().filterNotNull().collect{ uiState = uiState.copy(favorites = it) }
}
fun updateSearchText(searchText: String) {
this.searchText = searchText
viewModelScope.launch {
userPreferencesRepository.saveSearchTextPreference(searchText)
updateSearchResults()
}
}
fun selectAirport(airport: Airport?) {
viewModelScope.launch {
// val flightsForSelectedAirport = if (airport == null) {
// emptyList()
// } else {
// flightRepository.getAllDifferentAirports(airport.id).first()
// }
//
// uiState = uiState.copy(
// selectedAirport = airport,
// flightsForSelectedAirport = flightsForSelectedAirport
// )
if (airport != null) {
flightRepository.getAllDifferentAirports(airport.id).collect{ uiState = uiState.copy(flightsForSelectedAirport = it) }
} else {
uiState = uiState.copy(flightsForSelectedAirport = emptyList())
}
uiState = uiState.copy(selectedAirport = airport)
}
}
fun insertFavorite(depart: String, arrive: String) {
if (!uiState.favorites.checkIfFavoriteExists(depart, arrive)) {
val favorite = Favorite(departureCode = depart, destinationCode = arrive)
viewModelScope.launch {
flightRepository.insertFavorite(favorite)
}
}
}
companion object {
val factory : ViewModelProvider.Factory = viewModelFactory {
initializer {
FlightsScreenViewModel(
FlightSearchApplication().container.flightRepository,
FlightSearchApplication().container.userPreferencesRepository
)
}
}
}
}
fun List<Favorite>.checkIfFavoriteExists(depart: String, arrive: String): Boolean{
for (favorite in this){
if (favorite.departureCode == depart && favorite.destinationCode == arrive)
return true
}
return false
}
Pablo
06/08/2024, 7:03 AMLazyColumn(
modifier = Modifier.padding(8.dp)
) {
items(uiState.searchResult) { airport ->
AirportDetail(airport, onAirportSelected)
}
}
uiState.selectedAirport?.let {
FlightsForAirport(
airport = uiState.selectedAirport,
arrivals = uiState.flightsForSelectedAirport,
favorites = uiState.favorites,
onFavoriteSelected = onFavoriteSelected
)
}
lesincs
06/08/2024, 11:46 AMupdateSearchResults
function, you have two flow.collect()
in same suspend function which would be dangerous as for some types of flow mostly hot flow like StateFlow
or SharedFlow
, the collect()
suspends there forever until got canceled. So that might be the reason.