在导航图范围内注入viewmodel:在onCreate()之前NavController不可用 [英] injecting viewmodel with navigation-graph scope: NavController is not available before onCreate()

本文介绍了在导航图范围内注入viewmodel:在onCreate()之前NavController不可用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序中使用了导航组件,并且还在同一图中的多个片段之间使用了共享的ViewModel.现在,我要使用此.

I'm using a navigation-component in my application and also using shared ViewModel between multiple fragments that are in the same graph. Now I want to instantiate the ViewModel with this graph scope with this.

如您所知,在片段中我们应该在onAttach :

As you know, in fragments we should inject objects ( ViewModel,..etc ) in onAttach:

但是当我要执行此操作时(将ViewModel和一个图范围注入到onAttach中),就会发生此错误:

but when I want to do this (injecting ViewModel with a graph scope in onAttach), this error occurs:

IllegalStateException: NavController is not available before onCreate()

你知道我该怎么做吗?

推荐答案

简而言之,您可以懒惰地为ViewModel提供匕首ProviderLazy.

In short, you could provide the ViewModel lazily with dagger Provider or Lazy.

详细的解释是:

您的注射点正确.根据https://dagger.dev/android#when-to-inject

Your injections points are correct. According to https://dagger.dev/android#when-to-inject

DaggerActivity立即在以下位置调用AndroidInjection.inject() onCreate(),在调用super.onCreate()之前,DaggerFragment会执行 在onAttach()中也是如此.

DaggerActivity calls AndroidInjection.inject() immediately in onCreate(), before calling super.onCreate(), and DaggerFragment does the same in onAttach().

问题是在Android重新创建Activity和附加到FragmentMangerFragments以及可以提供NavController时之间的某种竞争状况.更具体地说:

The problem is some kind of race condition between when Android recreates the Activity and the Fragments attached to the FragmentManger and when the NavController can be provided. More specifically:

  1. 一个已附加FragmentsActivity被操作系统破坏(可以通过开发人员设置"中的请勿保留活动"来复制)
  2. 用户导航回到Activity,操作系统继续重新创建Activity
  3. Activity在重新创建时调用setContentView.
  4. 这将导致重新连接FragmentManager中的Fragments,这涉及调用Fragment#onAttach
  5. Fragment被注入Fragment#onAttach
  6. Dagger尝试提供NavController
  1. one Activity that has Fragments attached is destroyed by the OS (can be reproduced with "don't keep Activities" from "developer settings")
  2. user navigates back to the Activity, OS proceeds to recreate the Activity
  3. Activity calls setContentView while being recreated.
  4. This causes the Fragments in the FragmentManager to be reattached, which involve calling Fragment#onAttach
  5. The Fragment is injected in Fragment#onAttach
  6. Dagger tries to provide the NavController

但是,由于Activity#onCreate尚未完成,您不能从Activity那里获得NavController

BUT you cannot get the NavController from the Activity by this point, as Activity#onCreate has not finished yet and you get

IllegalStateException: NavController is not available before onCreate()

我发现的解决方案是懒惰地注入NavCotroller或依赖NavController的东西(例如ViewModel,因为Android需要NavController来获得导航范围的VideModels).这可以通过两种方式完成:

The solution I found is to inject provide the NavCotroller or things that depend on the NavController (such as the ViewModel, because Android needs the NavController to get nav-scoped VideModels) lazily. This can be done in two ways:

  • Lazy
  • Provided
  • with Lazy
  • with Provided

(REF: https://proandroiddev.com/dagger-2 -part-three-new-possibilities-3daff12f7ebf )

ie:将ViewModel注入到Fragment或导航器的实现中,如下所示:

ie: inject the ViewModel to the Fragment or implementation of navigator like this:

    @Inject
    lateinit var viewModel: Provider<ViewModel>

然后像这样使用它:

viewModel.get().events.observe(this) {....}

现在,ViewModel可以由Dagger提供,例如:

Now, the ViewModel can by provided by Dagger like:


    @Provides
    fun provideViewModel(
        fragment: Fragment,
        argumentId: Int
    ): CreateMyViewModel {

        val viewModel: CreateMyViewModel
                by fragment.navGraphViewModels(R.id.nested_graph_id)

        return viewModel
    }

在注入Fragment时,Dagger不会尝试解决配置,但在使用它时,将解决竞争条件.

Dagger won't try to resolve the provisioning when the Fragment is injected, but when it's used, hence, the race condition will be solved.

我真的很讨厌不能直接使用viewModels并需要使用Provider,但这是我看到的解决此问题的唯一解决方法,我敢肯定这是Google的疏忽(我不会责怪他们,因为跟踪Fragment和Activity荒谬的生命周期非常困难.

I really hate not being able to use my viewModels directly and need to use Provider, but it's the only workaround I see to solve this issue, which I'm sure it was an oversight by Google (I don't blame them, as keeping track of the absurd lifecycle of Fragment and Activities is so difficult).

这篇关于在导航图范围内注入viewmodel:在onCreate()之前NavController不可用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆