I am trying to build a simple listing app and to fetch data from url I use retrofit2. And then, I store in MutableLiveData<Resource> object. How can I list retrofit2 results in LazyColumn?
My composable:
@ExperimentalAnimationApi
@Composable
fun CarsScreen(
viewModel: CarListViewModel = hiltViewModel()
){
viewModel.getCarsFromAPI()
val carsLiveData = viewModel.carsLiveData.observeAsState()
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
){
GreetingSection()
}
LazyColumn(
modifier = Modifier.fillMaxSize(),
) {
itemsIndexed( ){
//TODO
}
}
}
Viewmodel:
@HiltViewModel
class CarListViewModel @Inject constructor(
private val carRepository: CarRepository
): ViewModel() {
val carsLiveData:MutableLiveData<Resource<CarsResponse>> = MutableLiveData()
fun getCarsFromAPI() = viewModelScope.launch {
carsLiveData.postValue(Resource.Loading())
val response = carRepository.getCarsFromAPI()
carsLiveData.postValue(handleCarResponse(response))
}
private fun handleCarResponse(response: Response<CarsResponse>) : Resource<CarsResponse> {
if(response.isSuccessful){
response.body()?.let{resultResponse ->
return Resource.Success(resultResponse)
}
}
return Resource.Error(response.message())
}
}
CodePudding user response:
observeAsState doesn't return a LiveData; it returns the data contained within the LiveData that you're observing.
Whenever that LiveData's value changes, recomposition is triggered, and you'll get a new value.
Change the name of property carsLiveData to just cars. You can use that directly as the items in your LazyColumn.
One other note - you're calling viewModel.getCarsFromAPI() inside the CarsScreen composable every time it's recomposed. You probably don't want to do that.
If you only want to get the list once, you could use a LaunchedEffect inside CarsScreen, something like:
// Copyright 2023 Google LLC.
// SPDX-License-Identifier: Apache-2.0
@Composable
fun CarsScreen(...) {
LaunchedEffect(Unit) {
viewModel.getCarsFromAPI()
}
...
}
If you want to update that list, pass some state into LaunchedEffect instead of Unit - whenever that state changes, the LaunchedEffect will be canceled (if currently running) and restarted.
