6

我在带有 HILT 的多模块 android 项目中面临这个问题。

 kotlin.UninitializedPropertyAccessException: lateinit property repository has not been initialized in MyViewModel

我的模块是

  1. 应用模块
  2. 视图模型模块
  3. 用例模块
  4. 数据源模块

'应用模块'

@AndroidEntryPoint
class MainFragment : Fragment() {
private lateinit var viewModel: MainViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View {
    return inflater.inflate(R.layout.main_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    viewModel.test()
}}

'视图模型模块'

class MainViewModel @ViewModelInject constructor(private val repository: MyUsecase): ViewModel() {
fun test(){
    repository.test()
}}

'用例模块'

class MyUsecase @Inject constructor() {

@Inject
lateinit var feature: Feature

fun doThing() {
    feature.doThing()
}

@Module
@InstallIn(ApplicationComponent::class)
object FeatureModule {
    @Provides
    fun feature(realFeature: RealFeature): Feature = realFeature
}
}

'数据源模块'

interface Feature {
fun doThing()
}

class RealFeature : Feature {
override fun doThing() {
    Log.v("Feature", "Doing the thing!")
}
}

依赖项是

MyFragment ---> MyViewModel ---> MyUseCase ---> DataSource

我对这段代码做错了什么,请纠正它。

4

5 回答 5

6

在您的活动类上方,您必须添加注释@AndroidEntryPoint,如下所示:

@AndroidEntryPoint 类 MainActivity : AppCompatActivity() {

于 2021-05-09T12:58:34.627 回答
1

除了将你所有的东西移到构造函数注入之外,你RealFeature并没有被注入,因为你手动实例化它而不是让 Dagger 为你构造它。请注意您的 FeatureModule 如何直接调用 RealFeature 的构造函数并为@Provides方法返回它。Dagger 将按原样使用这个对象,因为它认为你已经为它完成了所有设置。仅当您让 Dagger 构造它时,字段注入才有效。

您的 FeatureModule 应如下所示:

@Module
@InstallIn(ApplicationComponent::class)
object FeatureModule {
    @Provides
    fun feature(realFeature: RealFeature): Feature = realFeature
}

或使用@Binds注释:

@Module
@InstallIn(ApplicationComponent::class)
interface FeatureModule {
    @Binds
    fun feature(realFeature: RealFeature): Feature
}

这也突出了为什么你应该转向构造函数注入;使用构造函数注入,这个错误是不可能的。

于 2020-07-11T04:46:34.087 回答
0

首先,我认为您@Inject的 RealFeature 类中缺少您,因此 Hilt 知道如何注入依赖项。其次,如果您想注入一个不属于 Hilt 支持的入口点的类,您需要为该类定义自己的入口点。

除了使用@Provides方法编写的模块之外,您还需要告诉 Hilt 如何访问依赖项。

在你的情况下,你应该尝试这样的事情:

@EntryPoint
@InstallIn(ApplicationComponent::class)
interface FeatureInterface {
    fun getFeatureClass(): Feature
}

然后,当您想使用它时,请编写如下内容:

        val featureInterface =
        EntryPoints.get(appContext, FeatureInterface::class.java)
        val realFeature = featureInterface.getFeatureClass()

您可以在此处找到更多信息:

https://dagger.dev/hilt/entry-points

https://developer.android.com/training/dependency-injection/hilt-android#not-supported

于 2020-07-29T13:49:54.737 回答
0

代码中的问题是它@ViewModelInject不像@Inject在其他类中那样工作。您不能在 ViewModel 中执行字段注入。

你应该做:

class MainViewModel @ViewModelInject constructor(
  private val myUseCase: MyUsecase
): ViewModel() {

  fun test(){
    myUseCase.test()
  }
}

考虑对课程遵循相同的模式MyUsecase。依赖项应该在构造函数中传入,而不是@Inject在类主体中进行编辑。这种方式违背了依赖注入的目的。

于 2020-07-10T10:25:38.080 回答
0
class MainViewModel @ViewModelInject constructor(private val repository: HomePageRepository,
                                                 @Assisted private val savedStateHandle: SavedStateHandle)
: ViewModel(){}

而不是像这样初始化视图模型: private lateinit var viewModel: MainViewModel viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)

直接使用这个:

私有 val mainViewModel:MainViewModel 由 activityViewModels()

解释: 辅助保存状态句柄:将确保如果活动/片段使用@Android入口点和视图模型注入进行注释,它将自动注入所有必需的构造函数依赖项,这些依赖项可从相应的组件活动/应用程序中获得,这样我们就不会拥有在片段/活动中初始化视图模型时传递这些参数

于 2021-01-04T10:37:52.340 回答