Crea ViewModels con dipendenze   Parte di Android Jetpack.

Seguendo le best practice dell'iniezione delle dipendenze, i ViewModel possono accettare le dipendenze come parametri nel costruttore. Questi sono per lo più di tipi dei livelli dominio o dati. Poiché il framework fornisce i ViewModel, è necessario un meccanismo speciale per crearne le istanze. Questo meccanismo è l'interfaccia ViewModelProvider.Factory. Solo le implementazioni di questa interfaccia possono creare istanze di ViewModel nell'ambito corretto.

ViewModel con CreationExtras

Se una classe ViewModel riceve dipendenze nel suo costruttore, fornisci una factory che implementi l'interfaccia ViewModelProvider.Factory. Esegui l'override della funzione create(Class<T>, CreationExtras) per fornire una nuova istanza di ViewModel.

CreationExtras consente di accedere a informazioni pertinenti che aiutano a creare un'istanza di un ViewModel. Di seguito è riportato un elenco di chiavi a cui è possibile accedere dagli extra:

Chiave Funzionalità
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY Fornisce l'accesso alla chiave personalizzata che hai passato a ViewModelProvider.get().
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY Fornisce l'accesso all'istanza della classe Application.
SavedStateHandleSupport.DEFAULT_ARGS_KEY Fornisce l'accesso al bundle di argomenti da utilizzare per costruire SavedStateHandle.
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY Fornisce l'accesso a SavedStateRegistryOwner utilizzato per creare ViewModel.
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY Fornisce l'accesso a ViewModelStoreOwner utilizzato per creare ViewModel.

Per creare una nuova istanza di SavedStateHandle, utilizza la funzione CreationExtras.createSavedStateHandle() e passala a ViewModel.

CreationExtras con APPLICATION_KEY

Di seguito è riportato un esempio di come fornire un'istanza di un ViewModel che accetta un repository con ambito nella classe Application e SavedStateHandle come dipendenze:

    import androidx.lifecycle.SavedStateHandle
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.ViewModelProvider
    import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
    import androidx.lifecycle.createSavedStateHandle
    import androidx.lifecycle.viewmodel.initializer
    import androidx.lifecycle.viewmodel.viewModelFactory

    class MyViewModel(
        private val myRepository: MyRepository,
        private val savedStateHandle: SavedStateHandle
    ) : ViewModel() {

        // ViewModel logic
        // ...

        // Define ViewModel factory in a companion object
        companion object {

            val Factory: ViewModelProvider.Factory = viewModelFactory {
                initializer {
                    val savedStateHandle = createSavedStateHandle()
                    val myRepository = (this[APPLICATION_KEY] as MyApplication).myRepository
                    MyViewModel(
                        myRepository = myRepository,
                        savedStateHandle = savedStateHandle
                    )
                }
            }
        }
    }

Poi, puoi utilizzare questa factory per recuperare un'istanza di ViewModel:

import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun MyScreen(
    modifier: Modifier = Modifier,
    viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory)
) {
    // ...
}

Trasmettere parametri personalizzati come CreationExtras

Puoi passare le dipendenze a ViewModel tramite CreationExtras creando una chiave personalizzata. Questa opzione può essere utile se il tuo ViewModel dipende da oggetti non accessibili tramite la classe Application e APPLICATION_KEY. Un esempio di questo caso si verifica quando ViewModel viene creato all'interno di un modulo Kotlin Multiplatform e pertanto non ha accesso alle dipendenze di Android.

In questo esempio, ViewModel definisce una chiave personalizzata e la utilizza in ViewModelProvider.Factory.

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory

class MyViewModel(
    private val myRepository: MyRepository,
) : ViewModel() {
    // ViewModel logic

    // Define ViewModel factory in a companion object
    companion object {

        // Define a custom key using the factory function
        val MY_REPOSITORY_KEY = CreationExtras.Key<MyRepository>()

        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                // Get the dependency in your factory
                val myRepository = this[MY_REPOSITORY_KEY] as MyRepository
                MyViewModel(
                    myRepository = myRepository,
                )
            }
        }
    }
}

Puoi creare un ViewModel con un CreationExtras.Key direttamente nei tuoi composables.

import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.compose.viewModel
// ...
@Composable
fun MyApp(myRepository: MyRepository) {
    val extras = MutableCreationExtras().apply {
        set(MyViewModel.MY_REPOSITORY_KEY, myRepository)
    }
    val viewModel: MyViewModel = viewModel(
        factory = MyViewModel.Factory,
        extras = extras,
    )
}

Risorse aggiuntive

Per saperne di più su ViewModel e dipendenze, consulta le seguenti risorse aggiuntive:

Documentazione

Visualizza contenuti