Search code examples
androidlistkotlinandroid-roomkotlin-flow

Why when I add import runtime.getValue error "delegate must have a 'getValue(Nothing?, KProperty*>)' method" remains


I'm new and taking the android basics with compose course, and specifically the flight search project https://developer.android.com/codelabs/basic-android-kotlin-compose-flight-search, here you need to add a search for airports from the database. I created a database, made a dao, but I don’t understand why I can’t get a list of airports in this code: MainScreen()

...
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
...

@Composable
fun MainScreen(
    modifier: Modifier = Modifier,
    viewModel: MainViewModel = viewModel(factory = MainViewModel.factory)
) {
    val content = remember { mutableStateListOf<Favorite>() }

    val searchText by viewModel.searchText.collectAsState()
    val isSearching by viewModel.isSearching.collectAsState()
    val airportList by viewModel.airportList.collectAsState(emptyList())

    Scaffold(
        topBar = {
            AppTopBar()
        }
    ) {
        Column(
            modifier = modifier
                .padding(it)
                .fillMaxSize()
        ) {
            AppSearchBar(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp),
                searchText = searchText,
                isSearching = isSearching,
                airportList = airportList,
                viewModel = viewModel
            )
            LazyColumn {
                ...
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppSearchBar(
    modifier: Modifier = Modifier,
    searchText: String,
    isSearching: Boolean,
    airportList: List<Airport>,
    viewModel: MainViewModel
) {
    SearchBar(
        query = searchText,
        onQueryChange = viewModel::onSearchTextChange,
        onSearch = viewModel::onSearchTextChange,
        active = isSearching,
        onActiveChange = { viewModel.onToggleSearch() },
        placeholder = { Text("Input flight") },
        leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
        modifier = modifier
            .fillMaxWidth()
            .padding(16.dp)
    ) {
        LazyColumn {
            items(airportList) { airport ->
                Text(
                    text = airport.name,
                    modifier = ...
                )
            }
        }
    }
}
...
MainViewModel()

class MainViewModel(
    private val airportDao: AirportDao, private val favoriteDao: FavoriteDao
) : ViewModel() {

    private val _isSearching = MutableStateFlow(false)
    val isSearching = _isSearching.asStateFlow()

    private val _searchText = MutableStateFlow("")
    val searchText = _searchText.asStateFlow()

    private val _airportList = MutableStateFlow(emptyFlow<List<Airport>>())
    val airportList = _airportList.asStateFlow()

    private val _favoriteList = MutableStateFlow(favoriteDao.getFavorites())
    val favoriteList = _favoriteList.asStateFlow()

    fun onSearchTextChange(text: String) {
        _searchText.value = text
        _airportList.value = airportDao.getSearchResults(text)
    }

    fun onToggleSearch() {
        _isSearching.value = !_isSearching.value
        if (!_isSearching.value) {
            onSearchTextChange("")
        }
    }


    companion object {
        val factory : ViewModelProvider.Factory = viewModelFactory {
            initializer {
                val application = (this[APPLICATION_KEY] as FlightSearchApplication)
                MainViewModel(application.database.airportDao(), application.database.favoriteDao())
            }
        }
    }
}

in mainscreen() an error is thrown on the line val airportList by viewModel.airportList.collectAsState(emptyList())

I tried to make the same code as in the previous code lab, but I don't understand the concept of flow


Solution

  • private val _airportList = MutableStateFlow*<List<Airport>>(emptyList())*
    
    fun onSearchTextChange(text: String) {
            _searchText.value = text
            *viewModelScope.launch {
                airportDao.getSearchResults(text).collect { searchResults ->
                    _airportList.value = searchResults
                }
            }*
        }