不同Android风格的通用代码

mrzz3bfm  于 2022-12-25  发布在  Android
关注(0)|答案(3)|浏览(201)

我正在构建4种不同风格的Android应用程序。
我有一个类Customization.java,其中3个是相同的,1个是不同的。
因为我不能将同一个类同时放在主文件夹和风味文件夹中,所以我现在必须为这3种风味维护完全相同的类的3个副本。
有没有什么办法可以只保留这个类的两个版本?

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

1.我看了味道维度,但结果发现它们不适用于这种情况。
1.在其中一种风格中只保留一个文件,并通过我的构建脚本复制它。
我想知道有没有更干净的东西从盒子里拿出来。

jyztefdp

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脚本将类似于

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下。
所以,最终的项目结构看起来像

+ 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
4si2a6ki

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源集中找到重复的类,然后在编译过程中排除它,以避免类重复错误。

yiytaume

yiytaume3#

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中删除
此解决方案也适用于活动类

相关问题