bei*_*rad 7 android fragment-lifecycle dagger-2 android-viewmodel android-architecture-navigation
我在我的应用程序中使用导航组件,并在同一图中的多个片段之间使用共享 ViewModel。现在我想用这个图形范围实例化视图模型此。
如您所知,我们应该onAttach在片段中注入对象(ViewModel、..etc):
但是当我想这样做(在 中注入具有图形范围的 ViewModel onAttach)时,会发生此错误:
IllegalStateException: NavController is not available before onCreate()
Run Code Online (Sandbox Code Playgroud)
你知道我怎么做吗?
GaR*_*eTa 10
简而言之,您可以为ViewModel懒惰的人提供匕首Provider或Lazy.
长的解释是:
您的注射点是正确的。根据https://dagger.dev/android#when-to-inject
在调用 super.onCreate() 之前,DaggerActivity 立即在 onCreate() 中调用 AndroidInjection.inject(),而 DaggerFragment 在 onAttach() 中执行相同的操作。
问题是在 Android 重新创建Activity和Fragments附加到FragmentManger以及何时NavController可以提供之间的某种竞争条件。进一步来说:
Activity已Fragments附加的一个被操作系统破坏(可以通过“开发人员设置”中的“不保留活动”进行复制)Activity,操作系统继续重新创建ActivityActivitysetContentView在重新创建时调用。Fragmentsin FragmentManager,这涉及调用Fragment#onAttachFragment被注入中Fragment#onAttachNavController但是此时您无法NavController从获得Activity,因为Activity#onCreate尚未完成并且您得到
IllegalStateException: NavController is not available before onCreate()
Run Code Online (Sandbox Code Playgroud)
我找到的解决方案是懒惰地注入NavCotroller依赖于的东西NavController(例如ViewModel,因为Android需要NavController获取导航范围VideModels)。这可以通过两种方式完成:
LazyProvided(参考:https : //proandroiddev.com/dagger-2-part-three-new-possibilities-3daff12f7ebf)
即:将 注入ViewModel到Fragmentnavigator的或实现中,如下所示:
@Inject
lateinit var viewModel: Provider<ViewModel>
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
viewModel.get().events.observe(this) {....}
Run Code Online (Sandbox Code Playgroud)
现在,ViewModel可以由 Dagger 提供,例如:
@Provides
fun provideViewModel(
fragment: Fragment,
argumentId: Int
): CreateMyViewModel {
val viewModel: CreateMyViewModel
by fragment.navGraphViewModels(R.id.nested_graph_id)
return viewModel
}
Run Code Online (Sandbox Code Playgroud)
Dagger 在Fragment注入时不会尝试解决配置,但是当它被使用时,竞争条件将得到解决。
我真的很讨厌不能直接使用我的 viewModels 并且需要使用Provider,但这是我看到的解决这个问题的唯一解决方法,我确定这是谷歌的疏忽(我不怪他们,因为跟踪片段和活动的荒谬生命周期是如此困难)。
| 归档时间: |
|
| 查看次数: |
3543 次 |
| 最近记录: |