【发布时间】:2014-12-25 12:10:46
【问题描述】:
我曾经有以下项目风格:
- 苹果
- 橙色
最初唯一的区别是applicationId/packageName。现在有一个不同的 java 文件。确切地说,是一个自定义的 ArrayAdapter。解决方案是创建src/Apple 和src/Orange,它们都继承自src/main。我从src/main 中删除了java 文件,并将副本放入src/Apple 和src/Orange 并进行了适当的修改。世界上一切都很好。
快进几周,现在 Apple 和 Orange 之间大约有 10 个 java 文件不同。再次......没什么大不了的。易于处理。将src/Apple 和src/Orange 中的java 文件分开。
快进到今天。我需要稍微修改一下,因为我想拥有每个版本的免费和高级版本。免费版和高级版仅在 URL 上有所不同。我打算简单地创建新类型,称为:
- 苹果免费
- ApplePremium
- 无橙
- OrangePremium
但我有一个难题。从现在开始,src/Apple 和 src/Orange 有 10 个不同的文件已更改...如果我更改 AppleFree 中的任何 java 文件,我必须确保在 ApplePremium 中执行相同操作。我有点处于十字路口,希望我的问题在这一点上是有道理的。我提出了三种可能的解决方案,但我不确定如何实施它们/正确的方法是什么/解决方案不是我想要的。
解决方案 1:
使用 if 语句
if (BuildConfig.FLAVOR==appleFree) {//use free Url} else {// use premium url}
问题: 两个 Url 在技术上都编译到 apk 中。我不想要这个。
解决方案 2:
让 src/AppleFree 和 src/ApplePremium 以某种方式从 src/Apple 父目录继承。
问题:不知道该怎么做。
解决方案 3:
像这样在 build.gradle 中添加免费和高级网址吗?
productFlavors {
appleFree {
applicationId "com.example.apple.free"
versionName "1.0"
url "http://freeurl.com"
versionCode 1
}
applePremium {
applicationId "com.example.apple.premium"
versionName "1.0"
url "http://premiumurl.com"
versionCode 1
}
orangeFree {
applicationId "com.example.orange.free"
versionName "1.0"
versionCode 1
url "http://freeurl.com"
}
orangePremium {
applicationId "com.example.orange.premium"
url "http://premiumurl.com"
versionName "1.0"
versionCode 1
}
}
问题:不确定如何实现。
任何提示都是有帮助的。
编辑:
最终解决方案?
flavorGroups 'fruit', 'paid'
productFlavors {
apple {
flavorGroup 'fruit'
}
orange {
flavorGroup 'fruit'
}
free {
flavorGroup 'paid'
}
premium {
flavorGroup 'paid'
}
appleFree {
applicationId "com.example.apple.free"
versionName "1.0"
buildConfigField 'String', 'BASE_URL', 'http://freeurl.com'
versionCode 1
}
applePremium {
applicationId "com.example.apple.premium"
versionName "1.0"
buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com'
versionCode 1
}
orangeFree {
applicationId "com.example.orange.free"
versionName "1.0"
versionCode 1
buildConfigField 'String', 'BASE_URL', 'http://freeurl.com'
}
orangePremium {
applicationId "com.example.orange.premium"
buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com'
versionName "1.0"
versionCode 1
}
}
【问题讨论】:
-
对于解决方案 1,编译器应该优化掉未使用的代码,因此它实际上不会生成二进制文件。
-
真的吗?我相信我在#android-dev irc 上四处询问,似乎没有人对此完全确定。如果没有进入二进制文件会很好。无论如何要确定? (除了反编译)对我来说,接受 ADT 开发人员的话就足够了。不过,这给我留下了解决方案 #1 的另一个问题。如何使
productFlavors {}中的appleFree和applePremium与src/apple相关联? -
这是 Java 编译器的一个特性,它优化了具有静态最终条件的
if语句的未使用代码路径。我知道BuildConfig.DEBUG肯定有效。我会仔细检查BuildConfig.FLAVOR,因为它是String,但我希望它会起作用。我没有时间写一个完整的答案,但你应该调查风味组:tools.android.com/tech-docs/new-build-system/… -
感谢风味组。有这样的东西存在是有道理的。我将在今天晚些时候尝试使用 BuildConfig.FLAVOR 反编译示例应用程序,如果您对编译器的看法是正确的,那么似乎解决方案 1 可能是可行的方法。感谢您为我指明正确的方向。
-
根据我的测试,如果您对静态最终字符串执行条件,它看起来不会剥离代码。布尔值按预期工作。
标签: android gradle android-studio android-gradle-plugin build.gradle