Gradle 模块化、工程化管理

178 阅读2分钟

Gradle 模块化、工程化管理

Gradle在android日常开发工作中无处不在,可能你对Gradle原理不太清楚,但是快速掌握它的使用技巧,将为你带来事倍功半的效果。

Gradle

  • 通俗的讲它是基于JVM的构建工具,通过Groovy的脚本构建任务,并管理任务与任务之前的依赖

  • 构建生命周期三阶段,当然可以做监听这里我们不展开

    • 初始化阶段:解析setting.gradle文件,对参与构建的项目创建project对象

    • 配置阶段:解析每个project的build.gradle,完成以下任务

      • 加载插件

        //例如
        plugins {
            id 'com.android.application'
        }
        
      • 加载依赖

        //例如
        dependencies {
          ...
        }
        
      • 加载Task

      • 执行脚本,自定义插件、Gradle支持的API等

    • 执行阶段:执行加载的Task以及依赖的Task

循环优化Gradle依赖管理

一般情况下我们都是直接在build.gradle文件中定义依赖

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.navigation:navigation-fragment:2.3.5'
    implementation 'androidx.navigation:navigation-ui:2.3.5'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

但是随着项目中越来越大,如何管理上百上千个依赖?这里我们就要借助到Groovy的List

root目录新建config文件夹,在config文件夹中新建version.gradle,将配置相关的文件都放到项目的config文件夹统一管理,这里在ext中添加了函数ext.depen

ext {
    appcompat="1.2.0"
    material="1.2.0"
    constraintlayout="2.0.4"
    navigation_fragment="2.3.5"
    navigation_ui="2.3.5"
    junit="4.+"
    ext_junit="1.1.2"
    espresso_core="3.3.0"
    glide="4.8.0"
    androidx_core="1.3.2"
}
ext.depen = { android,obj ->
    android.each { entry ->
        if(entry.value instanceof Map){
            obj.api (entry.key){
                entry.value.each { childEntry ->
                    exclude(group:childEntry.key)
                    exclude(module:childEntry.value)
                }
            }
        }else {
            obj.api entry.value
        }
​
    }
}

新建dependencies.gradle

apply from: "../config/version.gradle"
​
ext {
    android = [
        "appcompat":"androidx.appcompat:appcompat:${appcompat}",
        "constraintlayout":"androidx.constraintlayout:constraintlayout:${constraintlayout}",
        "androidx.navigation:navigation-ui:${navigation_ui}" : [
                'androidx.navigation' : 'navigation-runtime',
                'androidx.customview' : 'customview',
                'androidx.drawerlayout' : 'drawerlayout',
                'com.google.android.material' : 'material'
        ],
        "navigation_fragment":"androidx.navigation:navigation-fragment:${navigation_fragment}",
    ]
​
    test = [
            "junit":"junit:junit:${junit}"
    ]
​
    androidTest = [
            "ext_junit":"androidx.test.ext:junit:${ext_junit}",
            "espresso_core":"androidx.test.espresso:espresso-core:${espresso_core}"
    ]
}

新建config.gradle,Gradle模块化,开发过程可以针对一些单独或则通用的配置单独的抽取,通过apply from ..... 引入

​
apply from: "../config/dependencies.gradle"
​
android {
    compileSdk 31
​
    defaultConfig {
        applicationId "com.tip.mode1"
        minSdk 21
        targetSdk 31
        versionCode 1
        versionName "1.0"
​
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
​
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
​
dependencies {
    def android = project.ext.android
    def test = project.ext.test
    def androidTest = project.ext.androidTest
​
    depen(android,getDelegate())
​
    test.each {k,v -> testImplementation v}
    androidTest.each {k,v -> androidTestImplementation v}
}
​

然后在每个project的build.gradle中添加即可,这样做的优点是能保持每个project简洁切修改方便

......
apply from: "../config/config.gradle"

代码提示的Gralde

这里我们采用自定义 kotlin+plugin + includeBuild管理,构建速度更快一些,支持自动补全和单机跳转,方便你更好的管理Gradle依赖

新建 module :version

修改 build.gradle

apply plugin: 'kotlin'
apply plugin: 'java-gradle-plugin'
​
buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
    }
}
​
repositories {
    jcenter()
    google()
}
​
dependencies {
    implementation gradleApi()
    implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
}
​
compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
​
gradlePlugin {
    plugins {
        version {
            id = 'com.tip.version'
            implementationClass = 'com.tip.version.VersionPlugin'
        }
    }
}
​

增加kt

import com.tip.Compile
import com.tip.Google
​
plugins {
    id 'com.android.application'
    id "com.tip.version"
}
​
apply from: "../config/config.gradle"
​
android {
    compileSdk Compile.minSdkVersion
    ......
}
​
dependencies {
​
    implementation Google.material
    ......
}    

资源分包

通过gradle的sourceSets属性

android {
    //...
    sourceSets {
        main {
            res.srcDirs(
                    'src/main/res',
                    'src/main/res_core',
                    'src/main/res_user',
            )
        }
    }
}
​
​

源码依赖与aar远程快速切换

我们在模块化过程中需要发布aar集成到主app,但是我们常常需要修改代码进行源码依赖,我们需要快速实现切换

include ':glide-source'
project(':glide-source').projectDir = new File("../../lib/retrofit-source")
configurations.all {
    resolutionStrategy {
        dependencySubstitution {
            substitute module( "com.github.bumptech:glide") with project(':glide-source')
        }
    }
}

代码传送门

\