前言
笔者在整理归纳所学知识中。一直会忽视gradle多维度
的使用。例如项目中之前遇到了。国际版app使用google支付。国内版使用微信支付。需要将google支付的sdk与微信支付的sdk分开集成。实现
- 国际版只有且仅有google支付SDK
- 国内版只有且仅有微信支付的SDK
原因也很简单。编译的时候apk不会那么大。
本文就对于Gradle多维度进行分析。如有错误请指正。
什么是多维度
新建一个项目。点击AS左下角的Build Variants
就会有一个debug
和release
这两个就是开发工具给我们创建的默认的两个变体。
而这两个是在build.gradle
中可以看到。我们不用管。
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
复制代码
如果我们在 buildTypes
中添加一个 国际版的 变体例如
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
//国际版
international{
}
}
复制代码
可以看到在Build Variants
中多了一个international
注意
目前这3个变体都是在一个维度。那如果我想将国内版和国际版变成一个新的维度该如何呢?
在 官网中能够知道。当需要配置多个维度的时候。可以采用 productFlavors
//需要指明维度
flavorDimensions "nation"
productFlavors{
//国际版
international{
}
//国内版
domestic{
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
复制代码
当完成如上的配置以后。那么目前就存在两个维度。一个是 debug
或者是release
这个也是AS给我们提供的默认维度。还有一个是我们自己创建的维度nation
。来确认是否是国际版还是国内版。
现在在看一下我们的Build Variants
小总结
从上面的小示例。我们能够知道。维度不过是将我们的变种进行分类。形成 维度1
乘以维度2
的变种。方便我们在实际开发中做到不同功能不同的apk.就如同我们最上面的需求。
- 国际版只有且仅有google支付SDK
- 国内版只有且仅有微信支付的SDK
更多维度如何使用
之前仅仅演示了2个维度。但是实际项目中我还需要更多的维度。例如我们项目中遇到的一个实际问题。台湾版本虽然也规划为国际版。因为使用的都是google支付。但是这个功能仅仅部分放出。并没有全部放出。这个时候我就需要更多的一个维度。去判断是否需要放开支付功能。
flavorDimensions "nation","pay"
productFlavors{
//国际版
international{
dimension "nation"
}
//国内版
domestic{
dimension "nation"
}
//显示支付
showpay{
dimension "pay"
}
//不显示支付
hidepay{
dimension "pay"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
复制代码
虽然还是在productFlavors
中配置的。但是对于每一个变种都使用了dimension
指定了他所在的维度是哪一个.
那么现在我就有3个维度了。除了之前的两个,还多了一个维度去判断是否显示支付。所以的现在的变种就应该是 2 x 2 x 2 一共8个
个人觉得维度并不是越多越好。越多后续的工作也显得更加麻烦。实际项目中。最后是否支付我是使用buildConfigField
做了额外的配置
flavorDimensions "nation"
productFlavors{
//国际版
international{
buildConfigField("Boolean", "isShowPay", "false")
}
//国内版
domestic{
buildConfigField("Boolean", "isShowPay", "true")
}
}
复制代码
维度的作用
回到刚刚的示例中。创建了2个维度。
- release / debug
- 国际版 / 国内版
在 src
下创建international
文件夹和domestic
文件夹。用于放置不同内容的代码。
什么叫不同内容的代码?
这么说吧。一般情况下。我们的代码放在了 src/main/java/...
下面。为了做不同的区分。例如国际版中显示国际版,国内版显示国内版本,你可以将 src/main/java/...
下的代码全部复制到不同的文件夹下面。然后修改代码。这样你指定什么版本的时候就编译对应文件下的代码。
这么说比较苍白。笔者模拟写一个示例。需求就是不同编译显示不同的文本。
代码非常简单,如下。在textview 中显示一下即可
object DebugTools {
fun getFlavors(): String {
return "这是默认的"
}
}
复制代码
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<TextView>(R.id.textview).text = DebugTools.getFlavors()
}
}
复制代码
默认的目录结构就如下所示。非常简单。正常运行以后。就会显示这是默认的
笔者创建两个不同的文件夹。并且将代码全部复制到对应的变种中。注意。此时src/main/java/...
中的代码就需要删除。删除的原因是因为。编译的时候会将变种和src/main/java/...
下一起进行编译。如果不删除就会出现有两个MainActivity
的情况。
以上就是笔者说的,将代码全部复制过去的情况。
相信你也发现问题了。如果哪天我需要修改DebugTools
这样的类。那么所有变种都需要修改。太麻烦了。完全不符合我们的设计规范。
实际项目中的做法,是将通用的部分放在src/main/java/...
,仅仅将有区别的代码放在对应的变种文件夹下。例如我们做的简单示例中。只有DebugTools
是不相同的。那么就将这一个进行区分即可。如下示例
打包不同依赖
知道了维度以及如何配置维度。还存在一个问题。我想引入的是不同的依赖。如果单纯使用implementation
。不管是国内版还是国际版都会引入这个库。这并不是我想要的。我想要的是 国内版 只有 微信的sdk. 国际版只有google支付的sdk.
为了演示。笔者将
- 国际版使用
Glide
作为图片加载框架 - 国内版使用
Coil
作为图片加载框架
在官网中其实也说明了如何去配置
只需要在依赖前面加上对应的变体名称即可
//国际版使用 Glide
internationalImplementation 'com.github.bumptech.glide:glide:4.12.0'
internationalAnnotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
//国内版使用Coil
domesticImplementation("io.coil-kt:coil:1.2.0")
复制代码
然后在不同变体的文件夹下面就可能愉快的使用不同的依赖作图片加载了