Reputation: 937
i'am trying to build an app with jetpack compose but when it's come to api call with view model i get an infinite loop. the app keep calling the api and i don't get why. here is my viewmodel :
class LibraryViewModel() : ViewModel() {
var library: ArrayList<PKIssue> = arrayListOf()
var loadLibrary by mutableStateOf(false)
init {
getLibrary()
}
fun getLibrary(){
viewModelScope.launch {
Press.issues(
result = object : result<ArrayList<Issue>, Error> {
override fun succeed(result: ArrayList<Issue>?) {
loadLibrary = true
if (result != null) {
library = result
}
}
override fun failed(error: Error?) {
loadLibrary = false
}
})
}
}
But as soon as i init my viewModel i get infinite call to my api, here is how i try to declare it :
@SuppressLint("StateFlowValueCalledInComposition")
@Destination
@Composable
fun HomeScreen(
navigator: DestinationsNavigator,
libraryViewModel: LibraryViewModel = LibraryViewModel()
) {
or inside the composable : val libraryViewModel = LibraryViewModel()
but i get the same problem, i am i missing something ? it seem that it wait the end of the api call to put loadLibrary at true but in the mean time it keep call getLibrary() in loop. Thanks for helping
Upvotes: 3
Views: 2761
Reputation: 200020
When you use
libraryViewModel: LibraryViewModel = LibraryViewModel()
You are directly constructing a brand new instance of your LibraryViewModel
every time that method recomposes. Since you probably read your loadLibrary
value once getLibrary
returns, that causes a recomposition of that method, hence the infinite loop (as the recomposition again causes another brand new instance to be created...which kicks off a load...which causes another recomposition).
Instead, you should be following the documentation on using ViewModels with Compose:
Add the androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1
dependency to your build.gradle
file
Use the viewModel()
method to instantiate your ViewModel.
fun HomeScreen(
navigator: DestinationsNavigator,
libraryViewModel: LibraryViewModel = viewModel()
) {
The viewModel()
method is what actually causes your ViewModel to be cached and stored across recompositions, navigating to a different screen, and across configuration changes. Since by using that method you'll only have a single instance of that ViewModel, you won't run into the same infinite loop.
Upvotes: 6