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

Dagger2 injection of a ViewModel without @Inject constructor

我有大型 Android ViewModel classes,它们往往有很多依赖关系(其中大部分是来自 Room 的 DAO,每个 SQLite table 一个)。有些有超过 10 个依赖项。

这很好,但是 @Inject 构造函数因参数而臃肿,并且仅包含用于设置构造函数参数注入成员的样板代码。

我想切换到 "regular" 注入成员,使用 @Inject 注释单独标识,就像其他(愚蠢的)classes.

这对于 Android 相关的 classes 是失败的(尽管 ViewModels 被宣传为非 Android 依赖,例如他们不使用 Android 框架)这样作为活动和片段。

解决方法是使用一个工厂,它是使用 HasActivityInjectorHasServiceInjector 等接口从 Application class 注入的。

Dagger 不提供任何 HasViewModelInjector,所以如果我坚持单独注入成员而不是注入构造函数,我得到的是:

error: [dagger.android.AndroidInjector.inject(T)] XXXViewModel cannot be provided without an @Inject constructor or from an @Provides-annotated method. This type supports members injection but cannot be implicitly provided.

如果我创建一个带有 @Provides 注释的模块来创建 ViewModel,这不会注入单个成员。

我是不是漏掉了什么(我的最后一句话是我的问题中最重要的部分)还是根本不可能注入成员,而我必须注入构造函数?


一点代码。

我想要的:

class MyViewModel extends ViewModel {
    @Inject
    MyDao myDao;
}

与我需要做的相比:

class MyViewModel extends ViewModel {
    private final MyDao myDao;

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

第一个代码块(我想要的)需要在模块中使用此方法:

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

但在这种情况下,myDao 字段为空。如何注入 @Inject-注释成员?

我想避免使用第二个代码块,如果我需要注入很多成员,它往往会创建一个包含许多参数的庞大构造函数。

有多种注入方式,我想你指的是字段注入。与构造函数注入不同,字段注入必须手动触发。为此,请在您的组件中定义一个方法,并将视图模型作为参数。

void inject(ViewModel viewModel)

然后也许从您的视图模型构造函数中调用此方法。

class MyViewModel extends ViewModel {
    private final MyDao myDao;

    @Inject
    MyDao myDao;

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