2

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). Some have more than 10 dependencies.

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.

I wanted to switch to "regular" injected members, identified individually with an @Inject annotation, like other (dumb) classes.

This fails for Android related classes (although ViewModels are advertised as non-Android dependent, e.g. they don't use the Android framework) such as activities and fragments.

The workaround for that is to use a factory, which is injected from the Application class using the nice HasActivityInjector, HasServiceInjector, etc. interfaces.

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:

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.

If I create a module that has a @Provides annotation to create the ViewModel, this doesn't inject individual members.

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. How to inject the @Inject-annotated members?

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.

4

1 回答 1

4

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

void inject(ViewModel viewModel)

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

class MyViewModel extends ViewModel {
    private final MyDao myDao;

    @Inject
    MyDao myDao;

    public MyViewModel() {
        MyComponent mycomponent = DaggerMyComponent.....
        myComponent.inject(this);
    }
}
于 2018-04-24T00:00:09.790 回答