美文网首页
正确的姿势来优化你的build.gradle

正确的姿势来优化你的build.gradle

作者: 六指禅 | 来源:发表于2016-07-22 10:38 被阅读3194次

转自:http://chenzhongjin.cn/2016/06/23/正确的姿势来优化你的build-gradle/

引言

eclipse 已经成功了过去式.人人 Android Studio 时代已经到来.面对 gradle .很多人都诚惶诚恐.甚至很多时候github clone下来的项目都不会编译.gradle version、gradle plugin version、sdk version、support version 的概念都没有分清楚.导致因为跟原作者的一些配置和本地拥有的环境不匹配而无法编译成功.刚好公司项目到了一個阶段性手尾.趁着有一点时间.特地记录一下.和大家一齐分享交流.

下面统一用我写的一個RecyclerView的开源项目 RvHelper 来作为sample代码:RvHelper-github

统一管理所有依赖

在项目中新建一個buildsystem文件夹.并且新建一個dependencies.gradle文件.文件夹名称和文件名字随意.自己使用的时候映射即可.如图:

然后再进行文件的编写

ext.versions = [
code : 1,
name : '1.0.0',

    minSdk     : 15,
    targetSdk  : 23,
    compileSdk : 23,
    buildTools : '23.0.3',

    // Library versions
    junit      : '4.12',
    supportLibs: '23.4.0',
    multidex   : '1.0.1',

]
ext.libraries = [
junit : "junit:junit:$versions.junit",
supportV4 : "com.android.support:support-v4:$versions.supportLibs",
supportAppCompat : "com.android.support:appcompat-v7:$versions.supportLibs",
supportDesign : "com.android.support:design:$versions.supportLibs",
supportRecyclerView : "com.android.support:recyclerview-v7:$versions.supportLibs",
supportCardView : "com.android.support:cardview-v7:$versions.supportLibs",
supportAnnotations : "com.android.support:support-annotations:$versions.supportLibs",

    //拆dex
    multidex             : "com.android.support:multidex:1.0.1",

]
上面只是提供了最简单的一些依赖的配置.这样做的好处就是.如果存在多个module.同时都依赖相同的 minSdk & targetSdk & compileSdk & buildTools & supportLibs 就变得非常的方便.比较好管理.

gradle version说明

首先.对于项目来讲.gradle version会在如下的文件里面进行声明.

可以看到我目前使用的版本是 gradle2.10.当然.其实本身下载Android Studio的时候自带也有一個默认的Gradle.如图:

不过如果你想自己想尝鲜的话.也可以到gradle官网进行下载.

下载好之后配置一下环境变量即可.
配置好之后也可以在项目中指定gradle文件夹.如图:

gradle plugin version说明

很多时候.gradle plugin版本和本地的as自带的版本不对应.然后刚好又被墙了.没有自备梯子.就导致无法编译.所以在open project之前对应自己本地as的版本来修改好是很重要的一件事.
首先.打开项目根目录的 build.gradle 如图:

类似的.现在我的as版本是 2.1.2.那么.我的gradle plugin version就应该对应就是

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
}
}
如果我的as版本是2.2pv3.那么将会是

classpath 'com.android.tools.build:gradle:2.2-alpha3'
当然其实本身如果你刚好在用as2.2pv3的话.其实你打开项目的时候.他就会机智的弹出让你升级的选择框了.

module中使用统一配置

首先需要在根目录的 build.gradle 中声明一下引入我们自己编写的配置单.

然后在对应自己项目的Android-Lib-Moduel或App-Module就可以直接这么使用.

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile libraries.junit
compile libraries.supportAppCompat
compile libraries.supportRecyclerView
}
这样就可以相对优雅的处理好各种依赖的版本一致性问题.

优雅的管理so库

很多时候第三方sdk都会提供多个版本的so库.而因为可能我们同时都会使用不同的sdk.然后有一些刚好没提供上.而我们想要正常使用.理应取所有so库的交集目录.

如:

armeabi
sdk1.so
sdk2.so
armeabi-v7a
sdk1.so
这种情况下.我们只能使用armeabi的目录.而删除掉 armeabi-v7a.因为如果你刚好apk安装到了架构是 armeabi-v7a 的手机上.他就会解压apk中的 armeabi-v7a 目录到/data/data/xxApp/lib. 而显然sdk2.so是不存在的.这个时候如果你代码有使用到sdk2.so的话.必然会出现找不到so库的问题.从而导致crash.

当然.我们可以直接只删除到剩下 armeabi文件夹.但是这种方式就有点麻烦.因为如果刚好sdk2.so我们发现业务不需要了.可以删了.而sdk1.so我们是有多个平台编译的so库了.为了更加好的效果.我也不在于apk大一点.这种情况下.又要把 armeabi-v7a 的东西copy回来.这样也太麻烦了.所以.我们通过gradle来实现.

首先.编辑项目根目录下的 gradle.properties文件.
添加一行

...

android.useDeprecatedNdk=true
然后.在app-module的 build.gradle 中

android {
//...
defaultConfig {
//xx
ndk {
//设置支持的SO库架构
abiFilters 'armeabi'//, 'armeabi-v7a', 'arm64-v8a'//, 'x86', 'x86_64'
}
}
}
直接随便根据自己需求来配置需要打包到apk的so库类型.

自定义生成的apk名称

as中默认只是生成app-debug.apk.这样看起来太单调了.看起来一点都不nice.所以我们都喜欢自定义打包生成的apk的名称能够自定义.很简单.只需要在app-module的build.gradle中配置

android {
//...
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent + "/${variant.buildType.name}",
"dreamliner-rvhelperSample-${variant.buildType.name}-V${variant.versionName}.apk".toLowerCase())
}
}
}
效果如下:

配置正式签名

很多时候我们接入微信/高德地图.都需要进行正式签名才可以正常校验成功和使用.as本身也提供了配置签名的可视化操作.
如图:

当然.我们更喜欢的是自己写配置清单.
首先在app-module下创建自己的签名和对应的密码.别名.别名密码等配置.

jks的创建就不详细描述了.自行google.主要讲的是配置 private.properties文件.
补充相关内容:

RELEASE_STORE_FILE=sample.jks //签名的名称
RELEASE_STORE_PASSWORD=123456 //签名的密码
RELEASE_KEY_ALIAS=sample //别名名称
RELEASE_KEY_PASSWORD=123456 //别名的密码
然后在使用的app-module的build.gradle下再进行配置.

android{
//...
signingConfigs {
release {
def filePrivateProperties = file("private.properties")
if (filePrivateProperties.exists()) {
Properties propsPrivate = new Properties()
propsPrivate.load(new FileInputStream(filePrivateProperties))
storeFile file(propsPrivate['RELEASE_STORE_FILE'])
storePassword propsPrivate['RELEASE_STORE_PASSWORD']
keyAlias propsPrivate['RELEASE_KEY_ALIAS']
keyPassword propsPrivate['RELEASE_KEY_PASSWORD']
}
}
}
}
然后直接在buildType中指定一下使用什么签名即可.

android{
buildTypes {
debug {
minifyEnabled false
signingConfig signingConfigs.release //指定使用上面配置好的签名内容
}

    release {
        minifyEnabled true
        shrinkResources true
        signingConfig signingConfigs.release
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

    preview {
        debuggable true // save debug mes
        minifyEnabled true
        shrinkResources true
        signingConfig signingConfigs.release
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

}
常用的差异化构建

比如我现在喜欢在debug的时候.我的app_name是rvHelper-debug.而到正式的时候就用rvHelper.这样自己使用的时候也能一眼就看出来在使用的是测试/正式的包.

android{
buildTypes {
debug {
resValue 'string', 'APP_NAME', 'rvHelper-debug'
resValue 'string', 'isDebug', 'true'
}

    release {
        resValue 'string', 'APP_NAME', 'rvHelper'
        resValue 'string', 'isDebug', 'false'
    }

    preview {
        resValue 'string', 'APP_NAME', 'rvHelper-preview'
        resValue 'string', 'isDebug', 'true'
    }
}

}
然后直接在 string.xml 中进行配置

<string name="app_name">@string/APP_NAME</string>
而在清单文件上面当然使用 @string/app_name.这样一配置下来.就可以实现你想要的差异构建的效果.
同理.我想根据debug/release来初始化的时候做不同的逻辑.比如在Application初始化的时候.

public class AppContext extends Application {

private static AppContext mInstance;

private boolean isDebug;

public static AppContext getInstance() {
    return mInstance;
}

@Override
public void onCreate() {
    super.onCreate();
    mInstance = this;
    initDebug();
    initNet();
    //如初始化net一样.把相关的图片加载框架/Log/其他有debug开关的一些依赖.都可以进行差异化构建
}

public boolean isDebug() {
    return isDebug;
}

private void initDebug() {
    isDebug = Boolean.parseBoolean(getString(R.string.isDebug));
}

private void initNet() {
    if (isDebug()) {
        //使用本地服务器/测试服务器的地址
    } else {
        //使用生成服的服务器地址
    }
}

}
这样就可以很好的进行差异化构建[和多渠道打包同一个概念]

FAQ

开启multidex的常见错误

在我之前的博客中有简单介绍过如何配置multidex.但是很多时候编译的时候就会因为javaMaxHeapSize不足导致无法编译成功.这个时候只需要加入一下配置即可.

android {
//...
dexOptions {
preDexLibraries = false
javaMaxHeapSize "4g"
}

}
exclude重复的jar版本等信息

很多时候我们用不同的jar包.里面都会有版本信息/日志等等文件会一齐进行打包.如果刚好同名.就会导致打包的时候出错.这个时候只需要根据报错提供的名称来进行exclude即可.如下:

android {
//...
packagingOptions {
exclude 'META-INF/notice.txt'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/license.txt'
exclude 'META-INF/services/javax.annotation.processing.Processor'
}

}
依赖aar

首先copy *.aar文件到对应的module的libs目录.然后在对应的module的build.gradle文件中进行配置.

allprojects {
repositories {
jcenter()
flatDir {
dirs 'libs'
}
}
}

dependencies {
compile(name: 'sampleAar', ext: 'aar')
}
总结

暂时把我平时使用的配置风格都大概过了一下.虽然都只是简单的介绍.但是基本都还算是完整.能够满足项目需求.如果有其他的疑问.欢迎留言.大家进行沟通交流.同时如果我上文中提及到的点有所疏漏.还有各位兄弟们提点一二.

相关文章

  • 正确的姿势来优化你的build.gradle

    转自:http://chenzhongjin.cn/2016/06/23/正确的姿势来优化你的build-grad...

  • 产品优化正确的打开姿势

    对已有功能的优化 以下所有的步骤都是思考的一个过程,有些过程需要记录下来,有些不需要,在实际工作中有些功能迭代在团...

  • 来,搭讪的正确姿势

    其实,我作业还没写完呢,但是经过多次的摧残之后,我真的忍不住想要吐槽一下了。在吐槽自己前,事前声明,我说的都是错的...

  • 性能优化-使用RecyclerView的正确姿势

    前言 本文是在作者Blankj基础上补充一些RecyclerView的正确姿势Tips 持续更新~ 数据处理和视图...

  • Android消息机制(六) 总结

    参考Android线程的正确使用姿势Android性能优化典范之多线程篇 Android多线程编程的总结Andro...

  • UITableView的优化

    TableView 优化提示 优化常识 正确使用 reuseIdentifier 来重用 Cells Cell 中...

  • 正确姿势减缓疲劳 你的姿势正确吗

    正确姿势减缓疲劳 你的姿势正确吗 在日常生活当中我们经常听到人们说坐有坐相,站有站相,由此可见,行为姿势对于我们的...

  • 姿势不正确,怎么奋斗?

    文/风言锋语 体育锻炼讲求姿势正确,模特表演也要求姿势正确,普通人奋斗也需要正确姿势?答案是肯定的。姿势不正确,奋...

  • iOS 面试 - 项目优化

    淘宝下拉加载更多如何优化 TableView的性能优化 1、通过正确的设置 reuseIdentifier 来重用...

  • 流放之路 正确姿势

    辛迪加正确姿势 辛迪加正确姿势.png 安全屋奖励.png 辛迪加掉落.png 猎魔正确姿势 重要猎魔配方.png

网友评论

      本文标题:正确的姿势来优化你的build.gradle

      本文链接:https://www.haomeiwen.com/subject/pikijttx.html