Короче говоря, вы могли лениво снабдить ViewModel
кинжалом Provider
или Lazy
.
Длинное объяснение:
Твои точки уколов верны. Согласно https://dagger.dev/android#when-to-inject
DaggerActivity вызывает AndroidInjection.inject () сразу в onCreate () перед вызовом super.onCreate (), а DaggerFragment делает то же самое в onAttach ().
Проблема заключается в каком-то состоянии гонки между тем, когда Android воссоздает Activity
и Fragments
, прикрепленный к FragmentManger
, и когда может быть предоставлен NavController
. Более конкретно:
- один
Activity
, к которому прикреплен Fragments
, уничтожен ОС (может быть воспроизведен с помощью "не сохранять действия" в "настройках разработчика")
- пользователь возвращается к
Activity
, ОС продолжает воссоздавать Activity
Activity
вызывает setContentView
при воссоздании.
- Это приводит к повторному подключению
Fragments
в FragmentManager
, что требует вызова Fragment#onAttach
Fragment
вводится в Fragment#onAttach
- Кинжал пытается дать
NavController
НО вы не можете получить NavController
от Activity
к этому моменту, поскольку Activity#onCreate
еще не закончен, и вы получаете
IllegalStateException: NavController is not available before onCreate()
Решение, которое я нашел, состоит в том, чтобы лениво вводить предоставление NavCotroller
или вещей, которые зависят от NavController
(например, ViewModel
, потому что Android нужен NavController
для навигации VideModels
). Это можно сделать двумя способами:
(ССЫЛКА: https://proandroiddev.com/dagger-2-part-three-new-possabilities-3daff12f7ebf)
то есть: введите ViewModel
в Fragment
или реализацию навигатора следующим образом:
@Inject
lateinit var viewModel: Provider<ViewModel>
затем используйте это так:
viewModel.get().events.observe(this) {....}
Теперь ViewModel
может быть предоставлен Dagger, например:
@Provides
fun provideViewModel(
fragment: Fragment,
argumentId: Int
): CreateMyViewModel {
val viewModel: CreateMyViewModel
by fragment.navGraphViewModels(R.id.nested_graph_id)
return viewModel
}
Dagger не будет пытаться разрешить подготовку при введении Fragment
, но когда он используется, следовательно, состояние гонки будет решено.
Я действительно ненавижу то, что не могу использовать мои модели viewModels напрямую, и мне нужно использовать Provider
, но это единственный обходной путь, который я вижу для решения этой проблемы, и я уверен, что это был недосмотр со стороны Google (я не виню их, поскольку отследить абсурдный жизненный цикл фрагментов и действий так сложно).
person
GaRRaPeTa
schedule
04.02.2020
onStart()
. Я использовал NavController, чтобы получить viewModelStore navGraph вonAttach()
@MohammedRampurawala - person beigirad   schedule 18.12.2019onCreate
вместоonAttach
. - person EpicPandaForce   schedule 19.12.2019