简体   繁体   English

没有@Inject构造函数的ViewModel的Dagger2注入

[英]Dagger2 injection of a ViewModel without @Inject constructor

I have large Android ViewModel classes that tend to have a lot of dependencies (most of them are DAOs from Room, one per SQLite table). 我有大型的Android ViewModel类,这些类往往具有很多依赖关系(大多数是Room的DAO,每个SQLite表一个)。 Some have more than 10 dependencies. 有些具有10个以上的依赖关系。

This is fine but the @Inject constructor is bloated with arguments, and contains only boilerplate code to set the injected members from the constructor arguments. 很好,但是@Inject构造函数带有很多参数,并且仅包含样板代码以从构造函数参数设置注入的成员。

I wanted to switch to "regular" injected members, identified individually with an @Inject annotation, like other (dumb) classes. 我想切换到“常规”注入成员,像其他(哑)类一样,分别用@Inject注释标识。

This fails for Android related classes (although ViewModels are advertised as non-Android dependent, eg they don't use the Android framework) such as activities and fragments. 对于Android相关类(例如,ViewModel被宣传为非Android依赖类,例如它们不使用Android框架),例如活动和片段,此操作将失败。

The workaround for that is to use a factory, which is injected from the Application class using the nice HasActivityInjector , HasServiceInjector , etc. interfaces. 解决方法是使用工厂,工厂通过使用不错的HasActivityInjectorHasServiceInjector等接口从Application类注入。

Dagger doesn't provide any HasViewModelInjector , so if I persist in injecting members individually instead of injecting the constructor, here's what I'm given: Dagger不提供任何HasViewModelInjector ,因此,如果我坚持单独注入成员而不是注入构造函数,则可以得到以下信息:

error: [dagger.android.AndroidInjector.inject(T)] XXXViewModel cannot be provided without an @Inject constructor or from an @Provides-annotated method. 错误:[dagger.android.AndroidInjector.inject(T)]如果没有@Inject构造函数或@Provides注释方法无法提供XXXViewModel。 This type supports members injection but cannot be implicitly provided. 此类型支持成员注入,但不能隐式提供。

If I create a module that has a @Provides annotation to create the ViewModel, this doesn't inject individual members. 如果我创建一个带有@Provides批注的模块来创建ViewModel,则不会注入单个成员。

Did I miss something (my last sentence is what's most important in my question) or is it simply not possible to inject members, and I have to inject the constructor? 我是否错过了某些内容(我的最后一句话是我的问题中最重要的一句话),或者根本无法注入成员,而我不得不注入构造函数吗?


A bit of code. 一点代码。

What I want: 我想要的是:

class MyViewModel extends ViewModel {
    @Inject
    MyDao myDao;
}

versus what I need to do: 与我需要做的:

class MyViewModel extends ViewModel {
    private final MyDao myDao;

    @Inject
    MyViewModel(MyDao myDao) {
        this.myDao = myDao;
    }
}

First block of code (what I want) requires this method in a module: 第一个代码块(我想要的)在模块中需要此方法:

@Provides
MyViewModel provideMyViewModel() {
    return new MyViewModel();
}

but in this case the myDao field is null . 但是在这种情况下, myDao字段为null How to inject the @Inject -annotated members? 如何注入@Inject注释的成员?

I want to avoid the use of the 2nd block of code, which tends to create a huge constructor bloated with many arguments, should I need to inject a lot of members. 我想避免使用第二个代码块,因为如果需要注入大量成员,它往往会创建一个庞大的构造函数,其中包含很多参数。

There are multiple ways of injection and I think you are referring to field injection. 有多种注入方式,我认为您是指现场注入。 Field injection, unlike constructor injection, must be triggered manually. 与构造函数注入不同,字段注入必须手动触发。 To do that, define a method in your component with the view model as parameter. 为此,请在组件中以视图模型为参数定义一个方法。

void inject(ViewModel viewModel)

And then call this method from your view model constructor perhaps. 然后从您的视图模型构造函数中调用此方法。

class MyViewModel extends ViewModel {
    private final MyDao myDao;

    @Inject
    MyDao myDao;

    public MyViewModel() {
        MyComponent mycomponent = DaggerMyComponent.....
        myComponent.inject(this);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM