不同android风格的通用代码

时间:2015-02-17 14:26:02

标签: android gradle android-gradle

我正在构建4种不同风格的Android应用程序。

我有一个班级Customization.java,其中3个是相同的,1个不同。

由于我不能将同一个类放在主文件夹和flavor文件夹中,所以我现在必须为这3种口味维护3个完全相同的类。

有什么方法可以保留这个类的两个版本吗?

到目前为止我考虑过的事情:

  1. 我看了味道尺寸,但事实证明它们不适用于这种情况。
  2. 只保留一个文件中的一个文件并通过我的构建脚本复制它。
  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中找到重复的类,然后在编译期间将其排除,以避免类重复错误。