Создание ViewModel с зависимостями . Часть Android Jetpack .

Следуя лучшим практикам внедрения зависимостей , ViewModels могут принимать зависимости в качестве параметров в своем конструкторе. В основном это типы из предметной области или уровня данных . Поскольку фреймворк предоставляет ViewModels, для создания их экземпляров требуется специальный механизм. Этот механизм — интерфейс ViewModelProvider.Factory . Только реализации этого интерфейса могут создавать экземпляры ViewModels в нужной области видимости .

ViewModels with CreationExtras

Если класс ViewModel получает зависимости в своем конструкторе, предоставьте фабрику, реализующую интерфейс ViewModelProvider.Factory . Переопределите функцию create(Class<T>, CreationExtras) , чтобы предоставить новый экземпляр ViewModel.

CreationExtras позволяет получить доступ к необходимой информации, которая помогает создать экземпляр ViewModel. Вот список ключей, к которым можно получить доступ из extras:

Ключ Функциональность
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY Предоставляет доступ к пользовательскому ключу, переданному в метод ViewModelProvider.get() .
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY Предоставляет доступ к экземпляру класса Application .
SavedStateHandleSupport.DEFAULT_ARGS_KEY Предоставляет доступ к набору аргументов, которые следует использовать для создания SavedStateHandle .
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY Предоставляет доступ к объекту SavedStateRegistryOwner , используемому для построения ViewModel .
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY Предоставляет доступ к объекту ViewModelStoreOwner , используемому для построения ViewModel .

Для создания нового экземпляра SavedStateHandle используйте функцию CreationExtras.createSavedStateHandle() и передайте её в ViewModel.

CreationExtras с APPLICATION_KEY

Ниже приведён пример того, как предоставить экземпляр ViewModel , который принимает в качестве зависимостей репозиторий , ограниченный областью видимости класса Application , и SavedStateHandle :

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

Затем вы можете использовать эту фабрику при получении экземпляра ViewModel:

import androidx.lifecycle.viewmodel.compose.viewModel

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

Передайте пользовательские параметры в качестве CreationExtras.

Вы можете передавать зависимости в вашу ViewModel через CreationExtras , создав пользовательский ключ. Это может быть полезно, если ваша ViewModel зависит от объектов, недоступных через класс Application и APPLICATION_KEY . Например, когда ваша ViewModel создается внутри модуля Kotlin Multiplatform и, следовательно, не имеет доступа к зависимостям Android.

В этом примере ViewModel определяет пользовательский ключ и использует его в 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,
                )
            }
        }
    }
}

Вы можете создать экземпляр ViewModel с помощью CreationExtras.Key непосредственно в ваших компонуемых объектах.

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

Дополнительные ресурсы

Для получения дополнительной информации о ViewModel и зависимостях см. следующие дополнительные ресурсы:

Документация

Просмотры контента

{% verbatim %} {% endverbatim %} {% verbatim %} {% endverbatim %}