[英]Better Dagger dependency injection based on build type and flavor?
I am using aproach to provide modules to Dagger described in answer of this question Android Customize Workflow for Product Flavors我正在使用 aproach 为 Dagger 提供模块,在这个问题的回答中描述了Android Customize Workflow for Product Flavors
Our approach is a bit different - we have Modules
in debug
build type in src/debug/java
and in release
build type in src/release/java
.我们的方法有点不同 - 我们在
src/debug/java
中有debug
构建类型的Modules
,在src/release/java
中有release
构建类型。 Our main module is called ApplicationModule
it includes all other.我们的主模块称为
ApplicationModule
它包括所有其他模块。
Modules
in src/debug/java
provides some custom behaviour for debugging, logging etc and overrides ApplcationModule
. src/debug/java
Modules
为调试、日志记录等提供了一些自定义行为,并覆盖了ApplcationModule
。
Now we have a need to have custom behaviour based on application flavor.现在我们需要有基于应用程序风格的自定义行为。
What would be correct approach to do that?这样做的正确方法是什么?
For example flavors A to C should provide custom behaviours, while flavors D to F should provide basic, default behaviour.例如,口味 A 到 C 应该提供自定义行为,而口味 D 到 F 应该提供基本的默认行为。
So far I came up with such.到目前为止,我想出了这样的。
src/flavorX/java/com.application.FlavorModule
src/flavorX/java/com.application.FlavorModule
都有相同的类src/main/java
src/main/java
提供了我的模块的默认行为Is there a better way to achieve such result?有没有更好的方法来实现这样的结果? Because I don't like empty
src/flavorX/java/com.application.FlavorModule
and don't like code duplication...因为我不喜欢空的
src/flavorX/java/com.application.FlavorModule
也不喜欢代码重复......
Little complicated but here's how I did it:有点复杂,但我是这样做的:
Create an interface MainComponent and keep it in src/main, this should contain anything that is not flavor specific创建一个接口 MainComponent 并将其保存在 src/main 中,这应该包含任何非特定于风味的内容
public interface MainComponent {
void inject(MyApplication o);
void inject(BusinessObject o);
Foo getFoo();
Activitycomponent plusActivityComponent(ActivityModule activityModule);
} }
Within each flavor create an interface that inherits from the above one在每种风格中创建一个继承自上述风格的接口
public interface FlavorComponent extends MainComponent {
//flavor specific injection stuff similar to SourceComponent
}
Within Debug/Beta/Release create the actual component and extend the FlavorComponent (giving you all the flavor specific niceties).在 Debug/Beta/Release 中创建实际组件并扩展 FlavorComponent(为您提供所有特定于风味的细节)。
@Singleton
@Component(modules = {ApplicationModule.class, FlavorModule.class,
BetaApplicationModule.class, AnotherModuleJustBecause.class})
public interface ApplicationComponent extends FlavorComponent {
void inject(NYTApplication a);
}
Notice that you can also include a flavor specific FlavorModule that can be different in each flavor or not include it in Release while including it in Beta.请注意,您还可以包含特定于风味的 FlavorModule,它可以在每种风味中不同,或者不包含在 Release 中,而将其包含在 Beta 中。
Also include a ComponentFactory within Debug/Beta/Release returning the common Flavor Component Interface还在 Debug/Beta/Release 中包含一个 ComponentFactory 返回通用的 Flavor 组件接口
public class ComponentFactory {
public static final FlavorComponent getComponent(Application context) {
return DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(context))
.build();
}
and finally from your Application class call:最后从您的应用程序类调用:
ComponentFactory.getComponent(this).inject(this);
The component factory will return the Build Type Component which will extend the Flavor's Component.组件工厂将返回构建类型组件,它将扩展 Flavor 的组件。
My solution was an adaptation of this article cited above我的解决方案是改编上面引用的这篇文章
I have an interface call ApplicationComponent in src/main:我在 src/main 中有一个接口调用 ApplicationComponent:
@Singleton
@Component(modules = [
FlavorModule::class,
Anyothermoduleyouhave::class
])
interface ApplicationComponent {}
Now, inside of each flavor folder, you have to create 2 files:现在,在每个风味文件夹中,您必须创建 2 个文件:
by the way: if you don't have any source folder you can create by adding on your gradle file:顺便说一句:如果您没有任何源文件夹,您可以通过添加您的 gradle 文件来创建:
java.srcDirs += ['src/main/kotlin', 'src/myFlavorCode/kotlin']
and creating the kotlin folder as well并创建 kotlin 文件夹
FlavorModule:风味模块:
@Module
class FlavorModule {
@[Provides Singleton]
fun getConfig(config: MySpecificFlavor1Config): FlavorConfig
}
FlavorConfig风味配置
class MySpecificFlavor1Config @Inject constructor() : FlavorConfig {
override fun getMyValueThatImLookingFor() = "flavor 1 woooooow"
}
Do the same for the Flavor 2对 Flavor 2 做同样的事情
Important: to make this work dynamically with dagger, use the same package path for both FlavorModule/FlavorConfig classes, like package br.com.main.config, this way dagger understands which FlavorModule to use
重要提示:为了使用 dagger 动态地工作,对 FlavorModule/FlavorConfig 类使用相同的包路径,比如包 br.com.main.config,这样 dagger 就知道要使用哪个 FlavorModule
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.