非 Activity Java 类中的 Dagger 2 注入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35605408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:21:15  来源:igfitidea点击:

Dagger 2 injection in non Activity Java class

javaandroiddependency-injectiondagger-2

提问by Adnan Mulla

I am trying to use Dagger2 for DI, it works perfectly fine for Activity/Fragment related classes where there is a onCreate lifecycle event. Now I have a plain Java class which I want to be injected. Any ideas as to how to go about it would be appreciated. The code I have looks like this :

我正在尝试将 Dagger2 用于 DI,它对于存在 onCreate 生命周期事件的 Activity/Fragment 相关类非常有效。现在我有一个想要注入的普通 Java 类。任何关于如何去做的想法将不胜感激。我的代码如下所示:

BasicMoviesUsecaseComponent.java -

BasicMoviesUsecaseComponent.java -

@PerActivity
@Component(dependencies = AppComponent.class, modules = BasicMoviesUsecasesModule.class)
public interface BasicMoviesUsecasesComponent {
    void inject(PaymentsManager paymentsManager);
}

DatabaseModule.java -

数据库模块.java -

    @Module
    public class DatabaseModule {
       @Provides @Singleton
       Realm provideRealmInstance(Context context) {

           return Realm.getInstance(context);
       }

       @Provides @Singleton
       DatabaseProvider provideDatabaseInstance(Realm realm) {

           return new DatabaseProvider(realm);
       }

       @Provides @Singleton
       SharedPreferences provideSharedPrefs(Context context) {

            return context.getSharedPreferences(context.getPackageName()+"_prefs", Context.MODE_PRIVATE);
       }

       @Provides @Singleton
       SharedPreferencesManager provideSharedPreferencesManager(SharedPreferences sharedPreferences) {
            return new SharedPreferencesManager(sharedPreferences);
       }

        @Provides @Singleton
        PaymentsManager providePaymentsManager(SharedPreferencesManager sharedPreferencesManager) {

              return new PaymentsManager(sharedPreferencesManager);

        }

}

AppComponent.java -

AppComponent.java -

  @Singleton
  @Component(modules = {
    ApplicationModule.class,
    DomainModule.class,
    DatabaseModule.class
   })

public interface AppComponent {

    Bus bus();
    Realm realm();
    DatabaseProvider dbProvider();
    SharedPreferencesManager sharedPreferencesManager();
}

Here is the class I need to inject the SharedPreferencesManager into and I am unable to do so :

这是我需要将 SharedPreferencesManager 注入的类,但我无法这样做:

MyManager.java -

MyManager.java -

 private class MyManager {
    private SharedPreferencesManager manager;

    @Inject
    MyManager(SharedPreferencesManager manager){
          this.manager = manager;           
    } 

    private void initializeDependencyInjector() {

          BMSApplication app = BMSApplication.getInstance();

          DaggerBasicMoviesUsecasesComponent.builder()
                 .appComponent(app.getAppComponent())
                 .basicMoviesUsecasesModule(new BasicMoviesUsecasesModule())
                 .build().inject(PaymentsManager.this);
    }

}

How do I call initializeDependencyInjector() ?

我如何调用 initializeDependencyInjector() ?

回答by David Medenjak

You should generally use constructor injection whenever possible. The call to component.inject(myObject)is mostly to be used for objects which you can not instantiate yourself (like activities or fragments).

您通常应该尽可能使用构造函数注入。调用component.inject(myObject)主要用于您无法实例化自己的对象(如活动或片段)。

Constructor injection is basically what you already did:

构造函数注入基本上是你已经做过的:

private class MyManager {
    private SharedPreferencesManager manager;

    @Inject
    MyManager(SharedPreferencesManager manager){
          this.manager = manager;           
    } 
}

Dagger will create the object for you and pass in your SharedPreferencesManager. There is no need to call init or something similar.

Dagger 将为您创建对象并传入您的SharedPreferencesManager. 不需要调用 init 或类似的东西。

The real question is how to obtainan object of MyManager. To do so, again, dagger will handle it for you.

真正的问题是如何获得的对象MyManager。再次这样做,dagger 会为您处理。

By annotating the constructor with @Injectyou tell dagger how it can create an object of that type. To use it, just inject it or declare it as a dependency.

通过注释构造函数,@Inject您可以告诉 dagger 它如何创建该类型的对象。要使用它,只需注入它或将其声明为依赖项。

private class MyActivity extends Activity {
    @Inject
    MyManager manager;

    public void onCreate(Bundle savedState){
        component.inject(this);  
    } 
}

Or just add a getter to a component (as long as SharedPreferenceManagercan be provided, MyManagercan also be instantiated):

或者只是给一个组件添加一个getter(只要SharedPreferenceManager能提供,MyManager也可以实例化):

@Component(dependencies = SharedPreferenceManagerProvidingComponent.class)
public interface MyComponent {

    MyManager getMyManager();
}

回答by Micha? Ziobro

I also encounter this problem. I have MailgunService that I am using in one of my textfield validators. This validator is made in such way that I can define it in XML layout as app:rule="mailgun|email".

我也遇到这个问题。我在我的文本字段验证器之一中使用了 MailgunService。这个验证器的制作方式让我可以在 XML 布局中将它定义为app:rule="mailgun|email".

So basically I am accessing validator inside custom view implementation, this validator needs service, and I want to use dagger in order to not have to create all this httpclient, retrofits, etc. Which is dependency hell if created manually.

所以基本上我在自定义视图实现中访问验证器,这个验证器需要服务,我想使用 dagger 以便不必创建所有这些 httpclient、改造等。如果手动创建,这是依赖地狱。

So I found such a way to do this.

所以我找到了这样的方法来做到这一点。

First inside your AppComponent you do:

首先在你的 AppComponent 里面你做:

interface  AppComponent { 
    ...
    // getters
    fun getMailgunService(): IMailgunService
}

Then in Application you make

然后在应用程序中你做

 companion object { lateinit var INSTANCE: MyApp }

Then inside your class where you want to inject IMailgun service from dagger AppComponent you can do

然后在您想要从 dagger AppComponent 注入 IMailgun 服务的类中,您可以执行

private var service: IMailgunService

 init {
        val component = DaggerAppComponent
            .builder()
            .application(CRMApp.INSTANCE)
            .build()

        service = component.getMailgunService()
    }

And it is injected and it works!

它被注入并且它起作用了!