java - 在 Dagger 2 中使用 AndroidInjections 贡献模块(抽象类)作为子组件

标签 java android dagger-2

我研究 Dagger 2 并尝试了解如何将其附加到现有项目中。现在我遇到了以下将依赖项注入(inject) BroadcastReceivers 的问题。我不能使用 DaggerReceiver 因为我的接收器已经扩展了另一个类。要在 BroadcastReceivers 中使用 AndroidInjection,我应该将 DispatchingAndroidInjector 注入(inject)到 Application 类中。我不想将带有 AndroidInjection 贡献者的模块包含到主要依赖关系图中,所以,据我所知,我应该将它放在 Application 类的专用组件中,但正因为如此出现单例重复。

这是我的例子(GitHub repo)

MainActivity 和其他类提供依赖的类

AppModule.class

@Module
public class AppModule {

    Application mApplication;

    public AppModule(Application application) {
        mApplication = application;
    }

    @Singleton
    @Provides
    Application providesApplication() {
        return mApplication;
    }
}

UtilityModule.class

@Module
public class UtilityModule {

    @Singleton
    @Provides
    FirstUtilityClass providesFirstUtility(Application app) {
        return new FirstUtilityClass(app);
    }

    @Singleton
    @Provides
    SecondUtilityClass providesSecondUtility(Application app) {
        return new SecondUtilityClass(app);
    }
}

MainComponent.class

@Singleton
@Component(modules = { AppModule.class, UtilityModule.class })
public interface MainComponent {

    void inject(MainActivity activity);
}

Application类提供DispatchingAndroidInjector的类

ReceiversModule.class

@Module
public abstract class ReceiversModule {

    @ContributesAndroidInjector
    abstract FirstReceiver contributesFirstReceiver();

    @ContributesAndroidInjector
    abstract SecondReceiver contributesSecondReceiver();
}

ReceiversComponent.class

@Singleton
@Component(modules = { AppModule.class, UtilityModule.class, ReceiversModule.class })
public interface ReceiversComponent {

    void inject(MyApplication application);
}

注入(inject)...

MyApplication.class

public class MyApplication extends Application implements HasBroadcastReceiverInjector {

    @Inject DispatchingAndroidInjector<BroadcastReceiver> mInjector;
    @Inject FirstUtilityClass mFirstUtility;
    @Inject SecondUtilityClass mSecondUtility;
    MainComponent mMainComponent;

    @Override
    public void onCreate() {
        AppModule appModule = new AppModule(this);
        mMainComponent = DaggerMainComponent.builder().appModule(appModule).build();
        // I should build new component only for Application class, because DispatchingAndroidInjector not required for another targets
        DaggerReceiversComponent.builder().appModule(appModule).build().inject(this); // Here created new scope
        super.onCreate();
        // do something
        mFirstUtility.doFistThings(getClass().getSimpleName());
        mSecondUtility.doSecondThings(getClass().getSimpleName());
    }

    public MainComponent getMainComponent() {
        return mMainComponent;
    }

    @Override
    public AndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
        return mInjector;
    }
}

MainActivity.class

public class MainActivity extends AppCompatActivity {

    @Inject FirstUtilityClass mFirstUtility;
    @Inject SecondUtilityClass mSecondUtility;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ((MyApplication) getApplication()).getMainComponent().inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Do something
        mFirstUtility.doFistThings(getClass().getSimpleName());
        mSecondUtility.doSecondThings(getClass().getSimpleName());
        // Sending broadcasts here
    }
}

Logcat 输出

FirstUtilityClass1: doing first things from MyApplication...

SecondUtilityClass1: doing second things from MyApplication...

FirstUtilityClass2: doing first things from MainActivity...

SecondUtilityClass2: doing second things from MainActivity...

FirstUtilityClass1: doing first things from FirstReceiver...

SecondUtilityClass1: doing second things from SecondReceiver...

您如何在日志中看到,ApllicationMainActivity 接收实用程序类的不同实例。我想将 ReceiversComponent 作为 MainComponent 的子组件。但是 ReceiversModule 是抽象的,我不能将它动态地添加到现有的组件实例中。

MainComponent.class

@Singleton
@Component(modules = { AppModule.class, UtilityModule.class })
public interface MainComponent {

    ReceiversComponent with(ReceiversModule module);

    void inject(MainActivity activity);
}

ReceiversComponent.class

@Subcomponent(modules = { ReceiversModule.class })
public interface ReceiversComponent {

    void inject(MyApplication application);
}

然后在 MyApplication 中:

// It does not work because I can't create ReceiverModule instance :(
mMainComponent.with(new ReceiversModule()).inject(this); 

如何将 ReceiversComponent 用作 MainComponent 的子组件? 我很清楚我做错了什么,但我就是不明白在哪里。也许有另一种方法可以解决我的问题?

最佳答案

我刚刚找到了答案!

由于我的 ReceiversModule 类有一个没有参数的默认构造函数,所以在 MainComponent 接口(interface)中描述子组件时,我可以跳过它作为参数:

MainComponent.class

@Singleton
@Component(modules = { AppModule.class, UtilityModule.class })
public interface MainComponent {

    ReceiversComponent withReceiversModule(); // Here is the reference to the subcomponent with abstract module

    void inject(MainActivity activity);
}

MyApplication.class

@Override
public void onCreate() {
    AppModule appModule = new AppModule(this);
    mMainComponent = DaggerMainComponent.builder().appModule(appModule).build();
    mMainComponent.withReceiversModule().inject(this); // It's works!!! :)
    super.onCreate();  
    // do something
    mFirstUtility.doFistThings(getClass().getSimpleName());
    mSecondUtility.doSecondThings(getClass().getSimpleName());
}

可能有人会觉得这是小事,但我花了好几天才搞定。我很高兴,因为我的代码变得更简洁了。感谢大家!

关于java - 在 Dagger 2 中使用 AndroidInjections 贡献模块(抽象类)作为子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48205344/

相关文章:

java - 在测试环境中使用 MariaDB,在生产环境中使用 sql server,如何同时使用一个选择? - Java, Spring

java - 如果我有 2 个 Maven 项目,而其中一个项目需要另一个作为库,我该如何避免 Eclipse 中出现冗余 "maven-update"

kotlin - Kotlin 中的 Dagger 2 : Is there a way to do injection for class with default parameterized constructor without using Module?

kotlin - Dagger 2 Kotlin - @Binds 方法的 @Named 限定符

java - Java 6 中默认支持 xinclude 吗?

java - JPA。 Eclipselink 没有为 mySQL 提供密码,而它应该提供密码

Android:WebView goback() 始终为重定向 URL 重新加载同一页面

java - Android 资源 : SQLiteDatabase Missing databases/***. 资源或目标文件夹中的 zip 文件不可写

java - 需要与 Java Android Studio 中的 TCP/IP 本地托管服务器通信

android - dagger android支持proguard规则