Dagger-Hilt:@ViewModelInject 没有注入 MyViewModel 并崩溃?
Dagger-Hilt: @ViewModelInject is not injecting MyViewModel and crash?
在探索 Dagger-Hilt 的 ViewModelInject 时,我遵循 https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodels
中的示例
我尝试将 ViewModel 注入我的 activity,如下所示
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
时有没有做错什么?
显然我错过了添加一个 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'
我想补充一点,如果您在一个 multi-module 项目中,您必须在 :app
模块上也有 kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
才能正常工作。
对我来说,所有依赖项都完美放置,但错过了继承 ViewModel class (androidx.lifecycle.ViewModel)
ViewModel()
class MainViewModel @ViewModelInject constructor(): ViewModel()
尝试通过在路径中查找(⇧⌘F 或 Ctrl+Shift+F)搜索您的 ViewModel 生成的 java 文件,如下所示。
如果没有自动生成 java 个文件。这意味着您忘记将此依赖项添加到模块的 gradle 文件中,该文件会为每个 @HiltViewModel 注释生成必要的 java 文件。
kapt "androidx.hilt:hilt-compiler:$version"
@ViewModelInject
在较新的 hilt
版本中已弃用
https://developer.android.com/reference/androidx/hilt/lifecycle/ViewModelInject
使用HiltViewModel
@HiltViewModel
class TasksViewModel @Inject constructor(
val taskRepository: TaskRepository
) : ViewModel() {
}
确保以下依赖项在您的 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"
在探索 Dagger-Hilt 的 ViewModelInject 时,我遵循 https://developer.android.com/training/dependency-injection/hilt-jetpack#viewmodels
中的示例我尝试将 ViewModel 注入我的 activity,如下所示
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
时有没有做错什么?
显然我错过了添加一个 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'
我想补充一点,如果您在一个 multi-module 项目中,您必须在 :app
模块上也有 kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
才能正常工作。
对我来说,所有依赖项都完美放置,但错过了继承 ViewModel class (androidx.lifecycle.ViewModel)
ViewModel()
class MainViewModel @ViewModelInject constructor(): ViewModel()
尝试通过在路径中查找(⇧⌘F 或 Ctrl+Shift+F)搜索您的 ViewModel 生成的 java 文件,如下所示。
如果没有自动生成 java 个文件。这意味着您忘记将此依赖项添加到模块的 gradle 文件中,该文件会为每个 @HiltViewModel 注释生成必要的 java 文件。
kapt "androidx.hilt:hilt-compiler:$version"
@ViewModelInject
在较新的 hilt
版本中已弃用
https://developer.android.com/reference/androidx/hilt/lifecycle/ViewModelInject
使用HiltViewModel
@HiltViewModel
class TasksViewModel @Inject constructor(
val taskRepository: TaskRepository
) : ViewModel() {
}
确保以下依赖项在您的 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"