我正在构建4种不同风格的Android应用程序。我有一个类Customization.java,其中3个是相同的,1个是不同的。因为我不能将同一个类同时放在主文件夹和风味文件夹中,所以我现在必须为这3种风味维护完全相同的类的3个副本。有没有什么办法可以只保留这个类的两个版本?
Customization.java
1.我看了味道维度,但结果发现它们不适用于这种情况。1.在其中一种风格中只保留一个文件,并通过我的构建脚本复制它。我想知道有没有更干净的东西从盒子里拿出来。
jyztefdp1#
我想把CommonsWare的评论转换成一个答案。然后我会解释最终的目录设置应该是什么样子。当然,您可以覆盖风味中的资源,因此,在main/res/layout/中使用通用资源,在yourFlavorHere/res/layout/中使用特定风味资源。因此,如果Customization Activity的布局文件名为activity_customization.xml,您将在src/main/res/layout目录下的三种风格之间保留其共享的公共副本,并将修改后的布局xml放在其对应的源集目录src/flavorFour/res/layout下,以供使用。其工作方式是,由于风格1到3(与风格4不同)没有提供它们自己的activity_customization.xml版本,因此它们将继承来自main源代码集的版本。Activity Java类比较棘手,另一种可能性是使用相同的Activity实现配置风格,以便从两个源目录中提取:一个是特定于口味的,一个是具有公共类实现的公共类。与资源不同的是,Java代码文件不会被合并或覆盖。因此,在main下以及在任何风味源集中,Java文件不能具有相同的完全限定类名。如果这样做,您将收到 duplicate class error。要解决这个问题,最简单的解决方案是将Customization活动移出main并移入每个风味源集中,这是因为风味目录是互斥的(相互之间,而不是main),从而避免了冲突。但这意味着四种风格中有三种风格有活动的重复副本--这是一个维护噩梦--仅仅因为其中一种风格需要对它进行一些更改。为了解决这个问题,我们可以引入另一个源目录,它只保存三种风格之间共享的公共代码文件。因此,build.gradle脚本将类似于
main/res/layout/
yourFlavorHere/res/layout/
Customization
activity_customization.xml
src/main/res/layout
src/flavorFour/res/layout
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中,使其可用于风格1到3。flavorFour所需的修改版本将放在其自己的源代码集src/flavorFour/java下。所以,最终的项目结构看起来像
java.srcDir
srcDirs
src/flavorX/java
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
4si2a6ki2#
我用这个来覆盖代码5年,只需添加一段代码到您的build.gradle。对于最新的Gradle插件(〉=3.4.0):
android { ...... applicationVariants.configureEach { ApplicationVariant variant -> AndroidSourceSet flavorSourceSet = android.sourceSets.findByName(variant.productFlavors[0].name); if (flavorSourceSet != null) { String flavorPath = flavorSourceSet.java.srcDirs[0].path; variant.javaCompileProvider.configure { task -> task.exclude { FileTreeElement elem -> !elem.isDirectory() && !elem.file.parent.startsWith(flavorPath) && new File(flavorPath, elem.path).exists(); } } } }
对于旧版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源集中找到重复的类,然后在编译过程中排除它,以避免类重复错误。
Main
yiytaume3#
Ravi K Thapliyal的解决方案不适用于我的gradle 3.5.3下面是一个可行的替代解决方案:将所有风格的通用代码移到一个文件夹中,例如:
然后将你的泛型代码复制到一个泛型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中删除此解决方案也适用于活动类
3条答案
按热度按时间jyztefdp1#
我想把CommonsWare的评论转换成一个答案。然后我会解释最终的目录设置应该是什么样子。
当然,您可以覆盖风味中的资源,因此,在
main/res/layout/
中使用通用资源,在yourFlavorHere/res/layout/
中使用特定风味资源。因此,如果
Customization
Activity的布局文件名为activity_customization.xml
,您将在src/main/res/layout
目录下的三种风格之间保留其共享的公共副本,并将修改后的布局xml放在其对应的源集目录src/flavorFour/res/layout
下,以供使用。其工作方式是,由于风格1到3(与风格4不同)没有提供它们自己的
activity_customization.xml
版本,因此它们将继承来自main
源代码集的版本。Activity Java类比较棘手,另一种可能性是使用相同的Activity实现配置风格,以便从两个源目录中提取:一个是特定于口味的,一个是具有公共类实现的公共类。
与资源不同的是,Java代码文件不会被合并或覆盖。因此,在
main
下以及在任何风味源集中,Java文件不能具有相同的完全限定类名。如果这样做,您将收到 duplicate class error。要解决这个问题,最简单的解决方案是将
Customization
活动移出main
并移入每个风味源集中,这是因为风味目录是互斥的(相互之间,而不是main
),从而避免了冲突。但这意味着四种风格中有三种风格有活动的重复副本--这是一个维护噩梦--仅仅因为其中一种风格需要对它进行一些更改。为了解决这个问题,我们可以引入另一个源目录,它只保存三种风格之间共享的公共代码文件。
因此,
build.gradle
脚本将类似于注意使用了
java.srcDir
(而不是srcDirs
),它将另一个Java源目录添加到已经存在的默认src/flavorX/java
中。现在我们需要做的就是将公共
Customization
活动文件放到src/common/java
中,使其可用于风格1到3。flavorFour
所需的修改版本将放在其自己的源代码集src/flavorFour/java
下。所以,最终的项目结构看起来像
4si2a6ki2#
我用这个来覆盖代码5年,只需添加一段代码到您的build.gradle。
对于最新的Gradle插件(〉=3.4.0):
对于旧版gradle插件:
它会在
Main
源集中找到重复的类,然后在编译过程中排除它,以避免类重复错误。yiytaume3#
Ravi K Thapliyal的解决方案不适用于我的gradle 3.5.3
下面是一个可行的替代解决方案:
将所有风格的通用代码移到一个文件夹中,例如:
然后将你的泛型代码复制到一个泛型src目录中:
这就是
Customization.java
类的泛型版本应该被复制到的地方。然后,创建一个特定于风格的代码副本到一个特定的src目录中,例如:build.gradle
脚本应按如下方式更新:注意:您的
Customization.java
类应从src/common/java
中删除此解决方案也适用于活动类