【问题标题】:Hilt ViewModel InjectionHilt ViewModel 注入
【发布时间】:2021-01-20 17:07:00
【问题描述】:

我一直在尝试解决我的问题,但我找不到任何东西...

MyApp.kt:

@HiltAndroidApp
class MyApp: Application()

MainActivity.kt

@AndroidEntryPoint
class MainActivity: AppCompatActivity() 

MyFragment.kt

class MyFragment: Fragment() {
    private val myViewModel: MyViewModel by viewModels()
}

MyViewModel.kt

class MyViewModel @ViewModelInject constructor(
    application: Application,
    myRepository: MyRepository, {*}
    @Assisted private val state: SavedStateHandle,
): AndroidViewModel(application)

MyRepository.kt

interface MyRepository { 
    fun test()
}

class MyRepositoryImpl @Inject constructor(): MyRepository { 
    override fun test() { print("") }
}

MyModule.kt

@Module 
@InstallIn(SingletonComponent::class)
abstract class MyModule {
    @Binds
    abstract fun bindsMyRepository(impl: MyRepositoryImpl): MyRepository
}

如果我用“{*}”注释该行,它可以正常工作,但由于我尝试添加我的自定义存储库,我收到了这个错误:

java.lang.RuntimeException:无法创建 MyViewModel 类的实例

原因:java.lang.NoSuchMethodException: [class android.app.Application]

你知道我错过了什么吗?

谢谢!

补充信息: 我忘了说这是一个多模块应用程序。

在第一个模块中,有一个基本的应用程序:MainActivity,一个清单(1)

在第二个模块中,有核心app:MyApp,一个manifest(2)

在第三个模块中,有模块:MyFragment、MyViewModel、MyRepository 和 MyModule,一个清单(3)

清单是这样的:

(1)

<manifest...>
    <application...
        android:name=".secondModule.MyApp">
</manifest>

(2)

<manifest...>
    <application>
        <provider...></provider>
    </application>
</manifest>

(3)

<manifest.../>

【问题讨论】:

  • 你需要这个接口做什么?
  • 我已经尽可能地简化了我的代码 :) 我有一个调用 Api 类的存储库,但现在我已经将其删除,直到它工作为止
  • 你需要添加一些 build.gradle 依赖,因为这听起来像是 Dagger + Hilt 版本不匹配。
  • 我当前的版本(在 IR42 回答之后):匕首:2.31.1,刀柄:2.31-alpha

标签: android kotlin dagger-hilt


【解决方案1】:
  • 首先注释您的片段
@AndroidEntryPoint
 class MyFragment: Fragment() {
  private val myViewModel: MyViewModel by viewModels()
}
  • 其次,您必须扩展 ViewModel 而不是 AndroidViewModel
class MyViewModel @ViewModelInject constructor(
   @Application context : Context ,
   myRepository: MyRepository, {*}
   @Assisted private val state: SavedStateHandle,
): ViewModel()
  • 用 ApplicationComponent 替换 SingletonComponent
 @Module 
@InstallIn(ApplicationComponent::class)
abstract class MyModule {
    @Binds
    abstract fun bindsMyRepository(impl: MyRepositoryImpl): MyRepository
}

PS : 不要忘记将您的应用程序类 ( MyApp ) 添加到清单文件中

【讨论】:

  • 感谢您的快速回答,我已经修改了我的两个文件。但是我仍然有这个错误: java.lang.IllegalStateException: Hilt Fragments must be attach to an @AndroidEntryPoint Activity MainActivity (我在活动和片段上都有注释“@AndroidEntryPoint”)我不能做的是使用注解“@Application”,“@ApplicationContext”是一样的吗?
  • 我已经编辑了答案再次检查它是否有效
  • 也许问题就在这里。这是一个多模块应用程序。在应用程序模块中,我的 AndroidManifest 属性为“android:name="MyApp"”。在另一个模块(片段所属的)中,清单几乎是空的,它只是一个声明
  • 你能在你的代码中添加一些你的清单文件的代码吗!
  • 对于您的替代品,此注释在 2.31-aplha 版本中是未知的,带有刀柄
【解决方案2】:

您的片段必须使用@AndroidEntryPoint

@AndroidEntryPoint
class MyFragment: Fragment() {
    private val myViewModel: MyViewModel by viewModels()
}

Dagger 2.30 中也删除了ApplicationComponent,但在androidx.hilt:hilt (@ViewModelInject) 中使用了它。 由于上面提到的库,他们在2.31.1 中添加了ApplicationComponent

将您的 Dagger 版本更新为 2.31.1(使用 SingletonComponent 而不是 ApplicationComponent)或使用新功能 Hilt View Models

@HiltViewModel
class MyViewModel @Inject constructor(
    private val application: Application,
    myRepository: MyRepository,
    private val state: SavedStateHandle,
): ViewModel()

【讨论】:

  • 感谢您的回答,我已将匕首更新到 2.31.1。我可以使用 HiltViewModel 注释,我已经尝试了你的解决方案,但我仍然遇到同样的问题:“IllegalStateException:Hilt Fragments 必须附加到 AndroidEntryPoint Activity。”,即使我已经用“AndroidEntryPoint”注释了我的所有片段和我的 MainActivity。
  • @JohnDoe 您是否还有其他没有@AndroidEntryPoint 的活动使用带有@AndroidEntryPoint 的片段?
  • 不,我没有看到任何包含 AndroidEntryPoint 片段的活动也没有 AndroidEntryPoint
猜你喜欢
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多