XCarb
XCarb

Reputation: 937

Jetpack compose api call with viewModel in infinite loop

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

Answers (1)

ianhanniballake
ianhanniballake

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:

  1. Add the androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1 dependency to your build.gradle file

  2. 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

Related Questions