美文网首页
Gradle技巧

Gradle技巧

作者: Alien的小窝 | 来源:发表于2016-08-21 17:54 被阅读374次

    Max OX用户安装配置gradle:

    假设您下载好的 Gradle 文件在 /Users/UFreedom/gradle 目录

    1. vim ~/.bash_profile
    2. 添加下面内容:export GRADLE_HOME = /Users/UFreedom/gradleexport export PATH=$PATH:$GRADLE_HOME/bin
    3. source ~/.brash_profile

    签名
    开发App时经常遇到Release版和Debug版共存问题,由于默认的签名不同,经常要卸载Debug版安装Release版,非常麻烦。
    有两种方法可以避免这种情况:

    1. 使用同一个签名 ;
    2. 使用不同包名

    方法1
    android {
    buildTypes {
    debug {signingConfig signingConfigs.myConfig}
    release {signingConfig signingConfigs.myConfig}
    }
    }

    方法2

    android {
       buildTypes {
           debug {packageNameSuffix ".debug"}
       }
    }
    

    引用 aar

    要输出 aar 文件,必须将 Module 配置为 library,在 gradle 文件中如下:

    1. 输出 aar : apply plugin: 'com.android.library'
    2. 输出 apk :apply plugin: 'com.android.application'

    一份 aar 文件其实就是一份 zip 包,和 jar 不同的是,它将一些资源文件、第三方库文件、so 文件等等都打包在内,而代码文件编译后压缩在在 classes.jar 中

    如 aar的内容


    Paste_Image.png

    依赖方式1
    导入方式,点击new -module

    Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png

    把这个文件夹当做一个项目来依赖了

    依赖方式2

    首先需要将 aar 文件放入引用 Module 的 libs 目录下,和一般的 jar 文件类似。然后在 gradle 配置文件中把 libs 目录加入依赖:

    repositories {
    flatDir {
    dirs 'libs'
    }

    最后
    compile(name: 'mylib-debug', ext: 'aar')

    依赖即可关联完毕。构建一下工程,在 Module 的 build/intermediates/exploded-aar
    目录下,可以看到有一些临时文件生成

    aar里面可以直接引用到资源文件,string,drawable等等
    且aar里面配置过的权限,直接引用后无需再在主工程里面配置了

    buildTypes节点下使用buildConfigField。

    下面是默认的buildTypes形式

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

    但是这里其实默认还有一个debug type,只不过默认不显示,显示完整如下

    buildTypes {
      release {
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
      }
      debug{
      }
    }
    
    

    默认的构建版本就这么两种,其实我们还可以构建新的版本

    如:

    android {
        buildTypes {
            staging {
                applicationIdSuffix ".staging"
                versionNameSuffix "-staging"
                buildConfigField "String", "API_URL","http://staging.example.com/api"
             }
        }
    }
    

    我们定义了一个staging版本,该版本定义了一个新的application id,这让其与debug和release版本的applicationID不同。假设你使用了默认的配置,那么applicationID将会是这样的:

    1. Debug: com.package
    2. Release: com.package
    3. Staging: com.package.staging

    还可以继承版本,复写其中的属性

    android {
           buildTypes {
               staging.initWith(buildTypes.debug) //继承debug构建版本
               staging {
                   applicationIdSuffix ".staging"
                   versionNameSuffix "-staging"
                   debuggable = false
               } 
            }
    }
    

    当我们打包编译项目时,我们能不能这里就可以设置一些参数信息,直接可以作用于项目,从而在项目中,动态根据build.gradle中设置的信息,进行一些代码层面的逻辑处理,比如在debug type下正常输出日志信息,但是release type下,屏蔽日志输出。那么就可以通过buildConfigField

    //注意,里面一定要应用签名
    buildTypes { 
      release {
        buildConfigField "boolean", "LOG_DEBUG", "false"
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release // ===========
      }
      debug{
        buildConfigField "boolean", "LOG_DEBUG", "true"  //=======
      }
    }
    

    因为我在项目中使用了开源库 Logger 进行日志输出,这个lib可以在Application的onCreate方法中进行开关设置,从而控制Log日志是否显示在console,所以最终使用如下:

    if(BuildConfig.LOG_DEBUG){
        Logger.init("AppPlusLog").setLogLevel(LogLevel.FULL);
    }else{
        Logger.init("AppPlusLog").setLogLevel(LogLevel.None);
    }
    

    gradle 的多模块构建

    模块耦合

    即你可以在一个模块中引用其他模块的属性,不建议你们这么做,完全可以在根目录下的build文件中定义这些属性。

    Paste_Image.png

    grade图形化让你运行模块间的任务变得简单,但是其没有为所有模块同时运行一个任务,所以如果你希望这么做,最快的方式是使用命令行(注意当前位置 ls下)。

    声明模块
    settings.gradle文件在根目录(不管主项目app是否依赖某个库,在项目下面都会被包含进来 )
    include ':app', ':mylibrary', ':mylibrary2'

    模块在某个文件夹下面

    project
    ├─── setting.gradle
    ├─── build.grade
    ├─── app
    │    └─── build.gradle
    └─── libraries
         ├─── library1
         │    └─── build.gradle
         └─── library2
              └─── build.gradle
    

    则需要这么定义

    include ':app', ':libraries:library1', ':libraries:library2'
    

    app 想依赖某个库

    dependencies { compile project(':libraries:library1')}
    

    gradle 构建生命周期

    如果你有多个模块,settings.gradle文件定义了这些模块的位置。如果这些子目录包含了其自己的build.gradle文件,gradle将会运行它们,并且将他们合并到构建任务中。这就解释了为什么你需要申明在一个模块中申明的依赖是相对于根目录(指的是:libraries:library1这种)。

    构建任务将所有的模块聚合在一起的时候.你可以配置所有的模块在根目录下的build.gradle。
    这让你能够简单的浏览到整个项目的配置,但是这将会变得一团乱麻,特别是当你的模块需要不同的插件的时候。
    另外一种方式是将每个模块的配置分隔开,这一策略保证了每个模块之间的互不干扰。这也让你跟踪构建的改变变得容易,
    因为你不需要指出哪个改变导致了哪个模块出现错误等。

    gradle的最大策略是混合。你可以在根目录下定义一个build文件去定义所有模块相同的熟悉,
    然后在每个模块中的build文件去配置只属于该模块的参数。
    Android studio遵循了该原则,其创建了一个build.gradle文件在根目录,
    然后再每个模块文件夹下创建了另外一个build文件。

    groovy语法

    在Java中,打印一天String应该是这样的:

    System.out.println("Hello, world!");
    在Groovy中,你可以这么写:

    println 'Hello, world!'
    你应该主要到几点不同之处:

    没有了System.out
    没有了方括号
    列结尾没有了;

    这个例子同样使用了单引号,你可以使用双引号或者单引号,但是他们有不同的用法。双引号可以包含插入语句。插入是计算一个字符串包含placeholders的过程,并将placeholders的值替换,这些placeholder可以是变量甚至是方法。Placeholders必须包含一个方法或者变量,并且其被{}包围,且其前面有$修饰。如果其只有一个单一的变量,可以只需要$。下面是一些基本的用法:

    def name = 'Andy'
    def greeting = "Hello, $name!"
    def name_size "Your name is ${name.size()} characters long."
    

    greeting应该是“ Hello,Andy”,并且 name_size 为 Your name is 4 characters long.

    string的插入可以让你更好的动态执行代码。比如

     def method = 'toString'
     new Date()."$method"()
    

    这在Java中看起来很奇怪,但是这在groovy里是合法的。

    Classes和members
    Groovy里面创建类和Java类似,举个例子:

    class MyGroovyClass {
           String greeting
           String getGreeting() {
               return 'Hello!'
            } 
    }
    

    注意到不论是类名还是成员变量都没有修饰符。其默认的修饰符是类和方法为public,成员变量为private

    当你想使用MyGroovyClass,你可以这样实例化:

    def instance = new MyGroovyClass()
    instance.setGreeting 'Hello, Groovy!'
    instance.getGreeting()   
    

    当你想使用MyGroovyClass,你可以这样实例化:

    def instance = new MyGroovyClass()
    instance.setGreeting 'Hello, Groovy!'
    instance.getGreeting()   
    

    你可以利用def去创建变量,一旦你为你的类创建了实例,你就可以操作其成员变量了。get/set方法groovy默认为你添加 。你甚至可以覆写它。

    如果你想直接使用一个成员变量,你可以这么干:

     println instance.getGreeting()
     println instance.greeting
    

    而这二种方式都是可行的。

    方法
    和变量一样,你不必定义为你的方法定义返回类型。举个例子

    java形式

    public int square(int num) {
           return num * num;
    } 
    square(2);
    
    

    groovy形式

     def square(def num) {
           num * num
     }
     square 4
     
    

    没有了返回类型,没有了入参的定义。def代替了修饰符,方法体内没有了return关键字。然而我还是建议你使用return关键字。当你调用该方法时,你不需要括号和分号。

    更简单的写法

    def square = { num ->
           num * num
    }
    square 8
    

    groovy闭包

    在grade中,我们经常使用闭包,例如Android代码体和dependencies也是。

    groovy集合

    有二个重要的容器分别是lists和maps。
    创建一个list很容易,我们不必初始化:
    List list = [1, 2, 3, 4, 5]
    为list迭代也很简单,你可以使用each方法:

    list.each() { element ->
           println element
    }
    

    你甚至可以使得你的代码更加简洁,使用it:

    list.each() {
           println it // it是闭包中的概念
    }
    

    map和list差不多:

    Map pizzaPrices = [margherita:10, pepperoni:12]
    如果你想取出map中的元素,可以使用get方法:

    pizzaPrices.get('pepperoni')
    pizzaPrices['pepperoni']
    

    同样的groovy有更简单的方式:

    pizzaPrices.pepperoni

    Build Variant

    android gradle 插件,允许对最终的包以多个维度进行组合。
    BuildVariant = BuildType x ProductFlavor

    product flavors用来为一个app创建不同版本。典型的例子是,一个app有付费和免费版

    buildTypes {
        debug {
        }
        release {
        }
    }
    
    productFlavors {
        pro {
        }
    
        fre {
        }
    }
    lintOptions {
        abortOnError false
    }
    
    
    

    这两个维度的组合,会产生如下包:

    proDebug
    proRelease
    freDebug
    proRelease
    

    当你添加了flavor dimensions,你就需要为每个flavor添加flavorDimension,否则会提示错误

    多个flavors构建变体
    在一些例子中,你可能需要创建一些product flavors的合并版本。举个例子,client A和client B可能都想要一个free和paid的版本,而他们又都是基于一样的代码,但是有不一样的颜色等。创建四个不同的flavors意味着有重复的配置。合并flavors最简单的做法可能是使用flavor dimensions,就像这样:

    android {
           flavorDimensions "color", "price"
           productFlavors {
               red {
                   flavorDimension "color"
               }
               blue {
                   flavorDimension "color"
               }
               free {
                   flavorDimension "price"
               }
               paid {
                   flavorDimension "price"
               }
           }
    }
    

    即 2个Color(red blue)*2个Price(free paid)即 4种
    redFree redPaid blueFree bluePaid

    总的构建是2(Debug release)*4 = 8

    blueFreeDebug and blueFreeRelease
    bluePaidDebug and bluePaidRelease
    redFreeDebug and redFreeRelease
    redPaidDebug and redPaidRelease
    

    相关文章

      网友评论

          本文标题:Gradle技巧

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