Tworzenie obiektów ViewModel z zależnościami, części Androida Jetpack.

Zgodnie ze sprawdzonymi metodami wstrzykiwania zależności obiekty ViewModel mogą przyjmować zależności jako parametry w konstruktorze. Są to głównie typy z warstw domeny lub danych. Ponieważ framework udostępnia obiekty ViewModel, do tworzenia ich instancji jest potrzebny specjalny mechanizm. Tym mechanizmem jest ViewModelProvider.Factory interfejs. Tylko implementacje tego interfejsu mogą tworzyć instancje ViewModel w odpowiednim zakresie.

ViewModel z CreationExtras

Jeśli klasa ViewModel otrzymuje zależności w konstruktorze, podaj fabrykę, która implementuje interfejs ViewModelProvider.Factory. Zastąp funkcję create(Class<T>, CreationExtras), aby utworzyć nową instancję ViewModel.

CreationExtras umożliwia dostęp do istotnych informacji, które pomagają utworzyć instancję ViewModelu. Oto lista kluczy, do których można uzyskać dostęp z dodatków:

Klucz Funkcje
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY Umożliwia dostęp do niestandardowego klucza przekazanego do ViewModelProvider.get().
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY Zapewnia dostęp do instancji klasy Application.
SavedStateHandleSupport.DEFAULT_ARGS_KEY Umożliwia dostęp do pakietu argumentów, których należy użyć do utworzenia SavedStateHandle.
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY Zapewnia dostęp do SavedStateRegistryOwner, który jest używany do tworzenia ViewModel.
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY Zapewnia dostęp do ViewModelStoreOwner, który jest używany do tworzenia ViewModel.

Aby utworzyć nową instancję SavedStateHandle, użyj funkcji CreationExtras.createSavedStateHandle() i przekaż ją do ViewModel.

CreationExtras z APPLICATION_KEY

Oto przykład sposobu udostępniania instancji ViewModel, która przyjmuje repozytorium w zakresie klasy ApplicationSavedStateHandle jako zależności:

    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
                    )
                }
            }
        }
    }

Następnie możesz użyć tej fabryki podczas pobierania instancji ViewModel:

import androidx.lifecycle.viewmodel.compose.viewModel

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

Przekazywanie parametrów niestandardowych jako CreationExtras

Zależności możesz przekazywać do ViewModel za pomocą CreationExtras, tworząc klucz niestandardowy. Może to być przydatne, jeśli ViewModel zależy od obiektów, które nie są dostępne za pomocą klasy ApplicationAPPLICATION_KEY. Przykładem takiej sytuacji jest utworzenie ViewModel w module Kotlin Multiplatform, który nie ma dostępu do zależności Androida.

W tym przykładzie element ViewModel definiuje klucz niestandardowy i używa go w elemencie 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,
                )
            }
        }
    }
}

Możesz utworzyć instancję ViewModelCreationExtras.Key bezpośrednio w funkcjach kompozycyjnych.

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,
    )
}

Dodatkowe materiały

Więcej informacji o klasach ViewModel i zależnościach znajdziesz w tych materiałach:

Dokumentacja

Wyświetlanie treści