基于构建类型和风格的更好的Dagger依赖注入?

时间:2014-02-11 20:53:36

标签: android dagger

我正在使用aproach为Dagger提供模块,在回答这个问题时提到Android Customize Workflow for Product Flavors

我们的方法略有不同 - 我们在Modules中的debug版本类型中src/debug/java以及release中的src/release/java版本类型中都有ApplicationModule。我们的主要模块叫Modules,它包含所有其他模块。

src/debug/java中的

ApplcationModule为调试,记录等提供了一些自定义行为,并覆盖了src/flavorX/java/com.application.FlavorModule

现在我们需要根据应用程序风格进行自定义行为。

这样做的正确方法是什么?

例如,口味A到C应该提供自定义行为,而口味D到F应该提供基本的默认行为。

到目前为止,我提出了这样的建议。

  • 所有风格(非构建类型)在src/main/java
  • 中具有相同的类
  • 为避免代码重复,只有A到C的风格提供自定义行为,而其他风格完全为空,以便项目可以编译。我的模块在src/flavorX/java/com.application.FlavorModule
  • 中提供了默认行为

有没有更好的方法来实现这样的结果?因为我不喜欢空{{1}}并且不喜欢代码重复......

2 个答案:

答案 0 :(得分:14)

有点复杂,但这就是我的做法:

创建一个接口MainComponent并将其保存在src / main中,这应该包含任何非特定于flavor的内容

public interface MainComponent {
    void inject(MyApplication o);

    void inject(BusinessObject o);

    Foo getFoo();

    Activitycomponent plusActivityComponent(ActivityModule activityModule);

}

在每个风格中创建一个继承自上述风格的界面

public interface FlavorComponent extends MainComponent {
//flavor specific injection stuff similar to SourceComponent
}

在Debug / Beta / Release中创建实际组件并扩展FlavorComponent(为您提供所有特定于风味的细节)。

@Singleton
 @Component(modules = {ApplicationModule.class, FlavorModule.class,
         BetaApplicationModule.class, AnotherModuleJustBecause.class})
public interface ApplicationComponent extends FlavorComponent {
     void inject(NYTApplication a);

 }

请注意,您还可以包含特定于风味的FlavorModule,它可以在每种风味中有所不同,或者不包含在Release中,同时将其包含在Beta中。

还在Debug / Beta / Release中包含一个ComponentFactory,返回常见的Flavor Component Interface

public class ComponentFactory {

public static final FlavorComponent getComponent(Application context) {
        return DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(context))
                .build();
    }

最后来自你的Application类调用:

ComponentFactory.getComponent(this).inject(this);

组件工厂将返回Build Type Component,它将扩展Flavor的Component。

答案 1 :(得分:0)

我的解决方案是对上面引用的article的改编

我在src / main中有一个接口调用ApplicationComponent:

    @Singleton
    @Component(modules = [

        FlavorModule::class,

        Anyothermoduleyouhave::class

    ])

    interface ApplicationComponent {}

现在,在每个风味文件夹中,您必须创建2个文件:

  1. FlavorModule(调用您的配置的抽象类)
  2. FlavorConfig(配置或所需的任何特定风味代码)

顺便说一句:如果您没有任何源文件夹,则可以通过添加gradle文件来创建:

        java.srcDirs += ['src/main/kotlin', 'src/myFlavorCode/kotlin']

并创建kotlin文件夹

FlavorModule:

    @Module
    abstract class FlavorModule {

        @[Binds Singleton]
        abstract fun getConfig(config: MySpecificFlavor1Config): FlavorConfig

    }

FlavorConfig

    class MySpecificFlavor1Config @Inject constructor() : FlavorConfig {
        override fun getMyValueThatImLookingFor() = "flavor 1 woooooow"
    }

对Flavor 2进行相同操作

重要提示:要使此功能与dagger一起动态运行,请为两者使用相同的包路径 FlavorModule / FlavorConfig类,例如br.com.main.config包,这种方式使dagger可以理解要使用哪个FlavorModule