【问题标题】:Dagger-Hilt: @ViewModelInject is not injecting MyViewModel and crash?Dagger-Hilt:@ViewModelInject 没有注入 MyViewModel 并崩溃?
【发布时间】:2020-06-30 13:55:25
【问题描述】:

在探索 Dagger-Hilt 的 ViewModelInject 时,我按照 https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodels 中的示例进行操作

我尝试将 ViewModel 注入到我的活动中,如下所示

import android.app.Application
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels
import androidx.hilt.Assisted
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.*
import androidx.savedstate.SavedStateRegistryOwner
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.HiltAndroidApp
import kotlinx.android.synthetic.main.activity_main.*
import javax.inject.Inject
import javax.inject.Singleton

@HiltAndroidApp
class MainApplication: Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels()

    private val textDataObserver =
        Observer<String> { data -> text_view.text = data }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewModel.showTextDataNotifier.observe(this, textDataObserver)
        btn_fetch.setOnClickListener { viewModel.fetchValue() }
    }
}

class MyViewModel @ViewModelInject constructor(
    @Assisted val savedStateHandle: SavedStateHandle,
    val repository: Repository
) :
    ViewModel(), LifecycleObserver {

    private val showTextLiveData
            = savedStateHandle.getLiveData<String>("DefaultKey")

    val showTextDataNotifier: LiveData<String>
        get() = showTextLiveData

    fun fetchValue() {
        showTextLiveData.value = repository.getMessage()
    }
}


@Singleton
class Repository @Inject constructor() {
    fun getMessage() = "From Repository"
}

它崩溃抱怨

     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.elyeproj.simplehilt.MyViewModel
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
        at androidx.hilt.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:69)

我尝试使用视图模型工厂(非注入方法)手动创建 ViewModel,它工作正常。

import android.app.Application
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels
import androidx.hilt.Assisted
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.*
import androidx.savedstate.SavedStateRegistryOwner
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.HiltAndroidApp
import kotlinx.android.synthetic.main.activity_main.*
import javax.inject.Inject
import javax.inject.Singleton

@HiltAndroidApp
class MainApplication: Application()

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels{
        MyViewModelFactory(this, Repository(), intent.extras)
    }

    private val textDataObserver =
        Observer<String> { data -> text_view.text = data }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewModel.showTextDataNotifier.observe(this, textDataObserver)
        btn_fetch.setOnClickListener { viewModel.fetchValue() }
    }
}

class MyViewModelFactory(
    owner: SavedStateRegistryOwner,
    private val repository: Repository,
    defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
    override fun <T : ViewModel> create(key: String, modelClass: Class<T>, handle: SavedStateHandle
    ): T {
        return MyViewModel(
            handle,
            repository
        ) as T
    }
}

class MyViewModel @ViewModelInject constructor(
    @Assisted val savedStateHandle: SavedStateHandle,
    val repository: Repository
) :
    ViewModel(), LifecycleObserver {

    private val showTextLiveData
            = savedStateHandle.getLiveData<String>("DefaultKey")

    val showTextDataNotifier: LiveData<String>
        get() = showTextLiveData

    fun fetchValue() {
        showTextLiveData.value = repository.getMessage()
    }
}

@Singleton
class Repository @Inject constructor() {
    fun getMessage() = "From Repository"
}

我在使用@ViewModelInject时做错了吗?

【问题讨论】:

标签: android android-viewmodel dagger-hilt


【解决方案1】:

@ViewModelInject 在较新的hilt 版本中已弃用

https://developer.android.com/reference/androidx/hilt/lifecycle/ViewModelInject

使用HiltViewModel

@HiltViewModel
class TasksViewModel @Inject constructor(
    val taskRepository: TaskRepository
) : ViewModel() {

}

【讨论】:

  • 我在做 Android 测试课程时尝试使用它,但我仍然收到此错误:InstantiationException: java.lang.Class 没有零参数构造函数
  • 如果像@AndrewChelix 这样的人在添加上述答案后遇到问题,请确保所有刀柄依赖项也应更新。
  • 这拯救了我的一天!谢谢!
  • ...和{从您的 build.gradle 文件中删除旧的 androidx.hilt:hilt-lifecycle-viewmodel 依赖项} - github.com/google/dagger/releases/tag/dagger-2.34
【解决方案2】:

显然我错过了添加一个 kapt,即kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'

我的build.gradle中的依赖列表如下

    implementation 'androidx.fragment:fragment-ktx:1.2.5'
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01"
    implementation 'com.google.dagger:hilt-android:2.28-alpha'
    kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
    kapt 'com.google.dagger:hilt-android-compiler:2.28-alpha'

为了完整起见,插件在下面

apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlin-kapt'

【讨论】:

  • 我的问题是,我在 Fragment 中使用 viewmodel,而在 Fragment 上我没有提到 @AndroidEntryPoint。我在 Activity 上提到了这一点,但在 Fragment 上没有提到。
  • 你拯救了我的一天!我缺少“androidx.lifecycle:lifecycle-viewmodel:2.2.0”的实现
  • 我遇到了同样的错误。就我而言,我缺少 implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"。当我将它添加到app/build.gradle 时,问题就解决了。
【解决方案3】:

我想补充一点,如果您在一个多模块项目中,则必须在 :app 模块上拥有 kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01' 才能使其正常工作。

【讨论】:

    【解决方案4】:

    尝试通过在路径中查找(⇧⌘F 或 Ctrl+Shift+F)搜索 ViewModel 生成的 java 文件,如下所示。

    如果没有自动生成的 java 文件。这意味着您忘记将此依赖项添加到模块的 gradle 文件中,该文件会为每个 @HiltViewModel 注释生成必要的 java 文件。

    kapt "androidx.hilt:hilt-compiler:$version"

    【讨论】:

      【解决方案5】:

      对我来说,所有依赖项都完美放置,但错过了继承 ViewModel 类 (androidx.lifecycle.ViewModel)

      ViewModel()

      class MainViewModel @ViewModelInject constructor(): ViewModel() 
      

      【讨论】:

        【解决方案6】:

        确保您的app/build.gradle 中有以下依赖项:

            // ViewModel
            implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0"
            implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
        
            // Hilt
            implementation 'com.google.dagger:hilt-android:2.33-beta'
            kapt 'com.google.dagger:hilt-compiler:2.33-beta'
        
            // Hilt ViewModel
            implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
            kapt "androidx.hilt:hilt-compiler:1.0.0-beta01"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-30
          • 1970-01-01
          相关资源
          最近更新 更多