Android Dagger Hilt: нужны ли нам аннотации области видимости для ViewModels?

в моем приложении у меня есть MainActivity, для которого требуется доступ к ViewModel. Я ввожу ViewModel с помощью DaggerHilt и аннотации @ViewModelInject. Кроме того, у меня есть два фрагмента в Activity, которым требуется доступ к одной и той же ViewModel, чтобы передавать данные друг другу с помощью наблюдаемых.

Проблема: я обнаружил, что всякий раз, когда один из моих фрагментов проходит onDestroy(), его ViewModel уничтожается. Это заставляет меня думать, что Activity и Fragments не используют одну и ту же ViewModel.

Мой вопрос: кто-нибудь знает, должны ли мы использовать аннотации области видимости для ViewModels в Dagger Hilt? Я не видел, чтобы об этом говорилось в документации Hilt или в руководствах / руководствах для разработчиков Android. Я предполагал, что они делают синглтоны уровня приложения ViewModels, что имело бы смысл.

Если нам действительно нужно использовать аннотации области видимости для ViewModels, знает ли кто-нибудь, какой уровень подходит?

Это мой код модели просмотра:

class MainActivityViewModel @ViewModelInject constructor(
    private val repo: Repo,
    private val rxSharedPrefsRepo: RxSharedPrefsRepo,
    private val resourcesRepo: ResourcesRepo,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {

person Mackalester    schedule 09.08.2020    source источник


Ответы (1)


Согласно Scoping in Android and Hilt blog post, с использованием @ViewModelInject означает, что объекты, которые вы передаете во ViewModel, ограничены ViewModel.

Объем ViewModel, однако, основан на том, как вы получаете ViewModel (с чем ViewModelStore связана ViewModel), а не на том, что контролирует Hilt. Если вы используете by viewModels() во фрагменте, тогда ViewModel привязан к фрагменту. Если вы используете by activityViewModels() или _ 5_, тогда ViewModel будет привязан к графику действий или навигации, соответственно.

Как упоминалось в сообщении в блоге, если вы хотите, чтобы объект был привязан к активности и сохранил изменения конфигурации, вы можете использовать @ActivityRetainedScoped Hilt для любого объекта и внедрить этот объект в оба фрагмента.

Следует ли вам использовать @ActivityRetainedScoped или ViewModel, в котором вы управляете областью действия отдельно от Hilt, описано в сообщении блога:

Преимущество определения области с помощью Hilt состоит в том, что типы с областью действия доступны в иерархии компонентов Hilt, тогда как с помощью ViewModel вам необходимо вручную получить доступ к типам с областью действия из ViewModel.

Преимущество определения области видимости с помощью ViewModel состоит в том, что вы можете иметь ViewModels для любых объектов LifecycleOwner в вашем приложении. Например, если вы используете библиотеку навигации Jetpack, у вас может быть ViewModel, прикрепленный к вашему NavGraph.

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

person ianhanniballake    schedule 09.08.2020
comment
Понятно, я неправильно понял, в чем была моя проблема. Оба моих дочерних фрагмента вызывали by viewModels(), что означает, что они были ограничены фрагментами. Использование by activityViewModels() исправило это для меня. Большое спасибо за помощь! - person Mackalester; 09.08.2020
comment
Обратите внимание, что вы также можете использовать by viewmodels ({requireParentFragment()}) для охвата ViewModel родительского фрагмента. Это было бы важно, если ваш родительский фрагмент не живет все время как активность. - person ianhanniballake; 09.08.2020