使用AndroidInjections贡献模块(抽象类)作为Dagger 2

时间:2018-01-11 10:52:54

标签: java android dagger-2

我研究Dagger 2并尝试了解如何将其附加到现有项目中。现在我面临以下问题:将依赖项注入BroadcastReceivers。我无法使用DaggerReceiver,因为我的接收器已经扩展了另一个类。要在AndroidInjection内使用BroadcastReceivers,我应该将DispatchingAndroidInjector注入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);
}

提供DispatchingAndroidInjectorApplication课程的课程

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);
}

注射...

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:从MyApplication做第一件事......

     

SecondUtilityClass1:从MyApplication做第二件事......

     

FirstUtilityClass2:从MainActivity做第一件事......

     

SecondUtilityClass2:从MainActivity做第二件事......

     

FirstUtilityClass1:从FirstReceiver做第一件事......

     

SecondUtilityClass1:从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的子组件? 我很清楚我做错了什么,但我无法理解在哪里。也许有另一种方法来解决我的问题?

1 个答案:

答案 0 :(得分:0)

我刚刚找到了答案!

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

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());
}

也许有人会认为这是一件小事,但我花了几天才达到它。我很高兴,因为我的代码变得更清洁了。谢谢大家!