我在我的应用程序中使用导航组件,并且还在同一个图中的多个 fragment 之间使用共享 ViewModel。现在我想用 this 用这个图范围实例化 ViewModel .
如您所知,在 fragment 中 we should inject objects ( ViewModel,..etc ) in onAttach
:
但是当我想这样做(在 onAttach
中注入(inject)带有图形范围的 ViewModel)时,会发生此错误:
IllegalStateException: NavController is not available before onCreate()
你知道我该怎么做吗?
最佳答案
简而言之,您可以提供 ViewModel
懒洋洋地用 Dagger Provider
或 Lazy
.
长的解释是:
您的注入(inject)点是正确的。根据 https://dagger.dev/android#when-to-inject
DaggerActivity calls AndroidInjection.inject() immediately in onCreate(), before calling super.onCreate(), and DaggerFragment does the same in onAttach().
问题是 Android 重新创建
Activity
之间的某种竞争条件。和 Fragments
附于FragmentManger
当 NavController
可以提供。进一步来说:Activity
有 Fragments
附件被操作系统破坏(可以通过“开发者设置”中的“不保留 Activity ”进行复制)Activity
, 操作系统继续重新创建 Activity
Activity
来电setContentView
在被重新创建时。 Fragments
在 FragmentManager
要重新连接,这涉及调用 Fragment#onAttach
Fragment
注入(inject) Fragment#onAttach
NavController
但是您无法获得
NavController
来自 Activity
至此,如 Activity#onCreate
还没有完成,你得到IllegalStateException: NavController is not available before onCreate()
我找到的解决方案是注入(inject)提供
NavCotroller
或依赖于 NavController
的东西(例如 ViewModel
,因为 Android 需要 NavController
才能获得导航范围的 VideModels
)。这可以通过两种方式完成:Lazy
Provided
(编号:https://proandroiddev.com/dagger-2-part-three-new-possibilities-3daff12f7ebf)
即:注入(inject)
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
}
当
Fragment
出现时,Dagger 不会尝试解析配置。被注入(inject),但是当它被使用时,竞争条件将被解决。我真的很讨厌不能直接使用我的 View 模型,需要使用
Provider
,但这是我看到的解决此问题的唯一解决方法,我确信这是 Google 的疏忽(我不怪他们,因为跟踪 fragment 和 Activity 的荒谬生命周期非常困难)。
关于android - 使用导航图范围 : NavController is not available before onCreate() 注入(inject) View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59388229/