我正在构建4种不同风格的Android应用程序。
我有一个班级Customization.java
,其中3个是相同的,1个不同。
由于我不能将同一个类放在主文件夹和flavor文件夹中,所以我现在必须为这3种口味维护3个完全相同的类。
有什么方法可以保留这个类的两个版本吗?
到目前为止我考虑过的事情:
我想知道是否有更清洁的东西。
答案 0 :(得分:104)
我想将CommonsWare的评论转换为答案。然后我将解释最终目录设置应该如何。我希望通过搜索帮助人们绊倒这个问题。
好吧,你可以覆盖口味中的资源。所以,有共同点 在
main/res/layout/
和特定风味的yourFlavorHere/res/layout/
。
因此,如果Customization
活动的布局文件被称为activity_customization.xml
,您将在src/main/res/layout
目录下的三种风格之间共享其公共副本,并将修改后的布局xml放置为由flavorFour
使用,在其相应的源集目录src/flavorFour/res/layout
下使用。
这样做的方式是,由于第一至第三种风味(不同于风味四)没有提供自己的activity_customization.xml
版本,它们将继承来自main
源集的风格。
这是活动Java类变得棘手。另一种可能性 即使用相同的活动实现配置flavor 从两个源目录中提取:一个特定于风味的目录和一个 与公共类实现的共同点。
与资源不同,Java代码文件不会被合并或覆盖。因此,您不能在main
下以及任何flavor源集中使用具有相同完全限定类名的Java文件。如果这样做,您将收到重复的类错误。
要解决此问题,最简单的解决方案是将Customization
活动移出main
并移入每个风味源集。这是有效的,因为flavor目录是相互排斥的(相互之间,而不是main
)因此避免了冲突。
但这意味着四种口味中的三种都有活动的副本 - 维护噩梦 - 只是因为其中一种口味需要对其进行一些更改。要解决此问题,我们可以引入另一个源目录,该目录仅保留三种风格之间共享的公共代码文件。
因此,build.gradle
脚本看起来像
android {
...
productFlavors {
flavorOne {
...
}
flavorTwo {
...
}
flavorThree {
...
}
flavorFour {
...
}
}
sourceSets {
flavorOne.java.srcDir 'src/common/java'
flavorTwo.java.srcDir 'src/common/java'
flavorThree.java.srcDir 'src/common/java'
}
}
请注意使用java.srcDir
(而不是srcDirs
)将另一个Java源目录添加到已存在的默认src/flavorX/java
。
现在我们需要做的就是删除Customization
中的常见src/common/java
活动文件,使其可用于第一到第三种口味。 flavorFour
所需的修改版本将位于src/flavorFour/java
设置的自己的源代码下。
因此,最终的项目结构看起来像
+ App // module
|- src
|- common // shared srcDir
|- java
|- path/to/pkg
|- CustomizationActivity.java // inherited by flavors 1, 2, 3
+ flavorOne
+ flavorTwo
+ flavorThree
+ flavorFour
|- java
|- path/to/pkg
|- CustomizationActivity.java // per-flavor activity class
|- res
|- layout
|- activity_customization.xml // overrides src/main/res/layout
|- main
+ java
|- res
|- layout
|- activity_customization.xml // inherited by flavors 1, 2, 3
答案 1 :(得分:2)
Ravi K Thapliyal 的解决方案在 gradle 3.5.3 中对我不起作用
这是一个有效的替代解决方案:
将所有口味通用的代码移动到一个文件夹中,例如:
src/common/java
然后将您的通用风味代码复制到通用 src 目录中:
src/generic/java
这就是您的 Customization.java
类的通用版本应该被复制到的地方。
然后,将您的风味特定代码的副本创建到特定的 src 目录中,例如
src/specific/java
您的 build.gradle
脚本应更新如下:
android {
...
productFlavors {
flavor1 {
...
}
flavor2 {
...
}
flavor3 {
...
}
flavor4 {
...
}
}
sourceSets {
flavor1.java.srcDirs('src/generic/java', 'src/common/java')
flavor2.java.srcDirs('src/generic/java', 'src/common/java')
flavor3.java.srcDirs('src/generic/java', 'src/common/java')
flavor4.java.srcDirs('src/specific/java', 'src/common/java')
}
}
注意:您的 Customization.java
类应该从 src/common/java
中删除
此解决方案也适用于活动类
答案 2 :(得分:0)
我用它覆盖了5年的代码,只需在您的build.gradle中添加一段代码即可:
android {
......
applicationVariants.all { ApplicationVariant variant ->
AndroidSourceSet flavorSourceSet = android.sourceSets.findByName(variant.productFlavors[0].name);
if (flavorSourceSet != null) {
variant.javaCompiler.doFirst {
String flavorPath = flavorSourceSet.java.srcDirs[0].path;
variant.javaCompiler.exclude { FileTreeElement elem ->
!elem.isDirectory() && !elem.file.parent.startsWith(flavorPath) &&
new File(flavorPath, elem.path).exists();
}
}
}
}
它将在Main中找到重复的类,然后在编译期间将其排除,以避免类重复错误。