产品风味(Product Flavor):发现重复类

60

我有一个问题,但是我已经坐在我的应用程序前数小时了,却无法理解问题所在。

我有一个安卓应用程序(用Kotlin编写),我想制作两个产品风味并覆盖产品风味中的一个类/文件:

所以我的gradle脚本如下:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'


android {
  ...
  productFlavors {
    foo {
      applicationId "com.foo"
    }
  }
}
我的文件结构如下:
 - src
    - androidTest
    - foo
      - java
        - com
          - example
            - Bar.kt
    - main
      - java
        - com
          - example
            - Bar.kt
    - test

基本上,我想要在foo产品口味中覆盖Bar.kt文件,但不知何故它不能正常工作:它说类Bar是重复的。

有什么提示吗?


6
具有特定味道的源码应该只存在于您定义的味道中(即不在主要源码中),因此您需要定义至少两种味道,并且仅将 Bar.kt 包含在这些味道的源码集中。 - Michael
嗯,也许你是对的...实际上我正在尝试覆盖一个Dagger模块...所以Bar.kt实际上是一个Dagger 2模块。 - sockeqwe
可能是Android gradle buildTypes: Duplicate class的重复问题。 - miensol
你可以查看我的回答:https://dev59.com/ql4b5IYBdhLWcg3w5VP9#66141092 - matdev
这有一些使用情况。我仍然希望优先考虑flavor模块中的类,并忽略main中的类。 - chitgoks
3个回答

70

变体文档中指出(强调我的):

注意:对于给定的构建变体,如果Gradle遇到了两个或更多定义了相同Java类的源集目录,则会抛出构建错误。例如,在构建Debug APK时,不能同时定义src/debug/Utility.java和src/main/Utility.java。这是因为Gradle在构建过程中查看这两个目录,并抛出重复类错误。如果希望为不同的构建类型使用不同版本的Utility.java,则可以使每个构建类型都定义自己的文件版本,并不将其包含在main/源集中

因此解决方案是使每个变体都具有其自己的Bar.kt版本,并将其从主源集中排除。


20
如果我有4-5种口味,其中3种使用相同的类并且集合使用特定代码,我需要在每个地方都复制它吗?还是可以使用sourceSets来完成?但无法使用sourceSets。 - Akhil Dad
4
@AkhilDad 我想你可以创建一个单独的模块来在不同版本之间共享代码。 - miensol
或者为此添加另一个口味维度。 - plaisthos

35

正如miensol所说,您不能将您的文件放在main和特定于flavor的文件夹中,并期望Gradle像Android资源系统一样工作。但是我找到了一种方法可以避免代码重复,因此您无需将Bar.kt复制到每个flavor文件夹中。

假设您有三个flavor:devprodmock。您希望您的特殊模拟Bar.ktmock中,但普通实现在devprod flavors中。您将模拟文件放入mock flavor 的专用文件夹中mock/java/com/something/,并将“默认”实现放入一个带有一些随机名称的新文件夹中,例如non-mock/java/com/something/ ,命名为“common”也很合理。现在,您必须告诉gradle这些flavor应该在哪里查找它们的Bar.kt类。

将以下内容放入您的build.gradle中:

android {
    ...
    sourceSets {
        prod {
            java.srcDirs('src/non-mock/java')
        }
        dev {
            java.srcDirs('src/non-mock/java')
        }
    }

}

1
完美运作,使用AS 3.4.2。谢谢! - 3c71

18

如果你有多个口味,如A、B和C

并且你的主要代码包含所有活动,对于A和C口味,你想要改变某些活动(例如ShoppingCartActivity)的某些功能

那么你需要进行以下更改:在所有三种口味中都放置ShoppingCartActivity(包括B),并从主代码中删除该文件,并将该文件声明到除主清单文件之外的所有清单文件中。

了解更多详细信息,请查看使用源集进行构建

- A
  - java
    - com
      - example
        - ShoppingCartActivity.kt(some changes)

- B
  - java
    - com
      - example
        - ShoppingCartActivity.kt

- C
  - java
    - com
      - example
        - ShoppingCartActivity.kt(new changes added)

- main
  - java
    - com
      - example
        **(remove from here)**

有没有办法在主要的 ShoppingCartActivity 上使用一个基础,以便在其他 flavor 中有另一个时,我可以使用 flavor 版本? - Igor Romcy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接