Unified dependency management composition builds

Posted by mentorbassment on Fri, 14 Jan 2022 14:46:23 +0100

background
In our AS projects, we often refer to multiple modules and many people participate in project development. Under this background, we will often encounter version conflicts and different compilesdkversions, resulting in larger packages and longer project running time. Therefore, the only way to optimize a project is to unify the dependent version.

You may encounter such a problem
In the architecture design phase, your dependency library is like this

After colleagues developed in parallel and merged the code, this became the case

 

Hahaha, this is the consequence of not doing a good job in dependency management! Here are three dependency management methods. If you are familiar with the first two, you can directly jump to the third composition builds. The third is recommended.

1, Alternative to Groovy ext extension functions
When we build a project using Groovy language, we extract config As a global variable control, gradle uses the ext extension function to uniformly configure dependencies, as follows:
 

Example code:

ext {
    android = [
            compileSdkVersion: 29,
            buildToolsVersion: "29",
            minSdkVersion    : 17,
            targetSdkVersion : 26,
            versionCode      : 102,
            versionName      : "1.0.2"
    ]

    version = [
            appcompatVersion       : "1.1.0",
            coreKtxVersion         : "1.2.0",
            supportLibraryVersion  : "28.0.0",
            androidTestVersion     : "3.0.1",
            junitVersion           : "4.12",
            glideVersion           : "4.11.0",
            okhttpVersion          : "3.11.0",
            retrofitVersion        : "2.3.0",
            constraintLayoutVersion: "1.1.3",
            gsonVersion            : "2.7",
            rxjavaVersion          : "2.2.2",
            rxandroidVersion       : "2.1.0",
            ..........ellipsis...........
    ]

    dependencies = [
            //base
            "constraintLayout"      : "androidx.constraintlayout:constraintlayout:${version["constraintLayoutVersion"]}",
            "appcompat"             : "androidx.appcompat:appcompat:${version["appcompatVersion"]}",
            "coreKtx"               : "androidx.core:core-ktx:${version["coreKtxVersion"]}",
            "material"              : "com.google.android.material:material:1.2.1",

            //multidex
            "multidex"              : "com.android.support:multidex:${version["multidexVersion"]}",

            //okhttp
            "okhttp"                : "com.squareup.okhttp3:okhttp:${version["okhttpVersion"]}",
            "logging-interceptor"   : "com.squareup.okhttp3:logging-interceptor:${version["okhttpVersion"]}",

            //retrofit
            "retrofit"              : "com.squareup.retrofit2:retrofit:${version["retrofitVersion"]}",
            "converter-gson"        : "com.squareup.retrofit2:converter-gson:${version["retrofitVersion"]}",
            "adapter-rxjava2"       : "com.squareup.retrofit2:adapter-rxjava2:${version["retrofitVersion"]}",
            "converter-scalars"     : "com.squareup.retrofit2:converter-scalars:${version["retrofitVersion"]}",
			..........ellipsis...........
    ]
}

After the dependency is written, click build. Exe in the root path gradle
Add apply from: "config.gradle"

Then, under the module you need to rely on, click build In gradle

dependencies {
    ...
    // Retrofit + okhttp dependent packages
    api rootProject.ext.dependencies["retrofit"]
    ...
    }
 

 

The above is the dependency management method of Groovy ext extension function. This method can achieve version dependency, but the biggest disadvantage is that the code cannot be tracked. You want to find the rootproject in the above example code Ext.dependencies ["retrofit"] this dependency needs to be manually switched to config Gradle to search and find, readability is very poor.

2, Using buildSrc+kotlin
buildSrc is a particularly popular version dependent management method in recent years. It has the following advantages:

Support two-way tracking
buildSrc is the default plug-in for Android. This is the only place that can be modified globally
Support the code completion of Android Studio. The following demonstration example is from the network
 

 

Refer to:

Kotlin + buildSrc for Better Gradle Dependency Management – Handstand Sam

Disadvantages: buildSrc dependency update will rebuild the whole project. The larger the project, the longer the reconstruction time, resulting in unnecessary waste of time.

3, Composing builds
Composing builds: A composite build is simply a build that includes other builds. In many ways a composite build is similar to a Gradle multi-project build, except that instead of including single projects, complete builds are included. (composing builds is just a build that contains other builds. In many ways, composite builds are similar to gradle multi project builds, except that it includes a complete build rather than a single project.)

The advantages of using this method are:
1. Support one-way tracking
2. Automatic completion
3. When relying on updates, the entire project will not be rebuilt

Mode of use
1. Create a new module named VersionPlugin (from)
2. Under the new module, click build Add the following code to the gradle file:
 

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // Because the Kotlin plug-in needs to be added
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10"
    }
}

apply plugin: 'kotlin'
apply plugin: 'java-gradle-plugin'

repositories {
    // jcenter needs to be added, otherwise it will prompt that gradlePlugin cannot be found
    jcenter()
    google()
}

dependencies {
    implementation gradleApi()
    implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10"
}

compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}
compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

gradlePlugin {
    plugins {
        version {
            // The plug-in needs to be referenced by id in the app module
            id = 'com.controler.versionplugin'
            // The path to the class that implements the plug-in
            implementationClass = 'com.controler.versionplugin.VersionPlugin'
        }
    }
}

 3. Create a new dependencymanager under VersionPlugin/src/main/java / package name / directory KT file, add your dependency configuration, such as:

package com.controler.versionplugin

/**
 * Configuration and build related
 */
object BuildVersion {
    const val compileSdkVersion = 29
    const val buildToolsVersion = "29.0.2"
    const val minSdkVersion = 17
    const val targetSdkVersion = 26
    const val versionCode = 102
    const val versionName = "1.0.2"
}

/**
 * Project related configuration
 */
object BuildConfig {
    //AndroidX
    const val appcompat = "androidx.appcompat:appcompat:1.2.0"
    const val constraintLayout = "androidx.constraintlayout:constraintlayout:2.0.4"
    const val coreKtx = "androidx.core:core-ktx:1.3.2"
    const val material = "com.google.android.material:material:1.2.1"
    const val junittest = "androidx.test.ext:junit:1.1.2"
    const val swiperefreshlayout = "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
    const val recyclerview = "androidx.recyclerview:recyclerview:1.1.0"
    const val cardview = "androidx.cardview:cardview:1.0.0"

    //Depend
    const val junit = "junit:junit:4.12"
    const val espresso_core = "com.android.support.test.espresso:espresso-core:3.0.2"
    const val guava = "com.google.guava:guava:24.1-jre"
    const val commons = "org.apache.commons:commons-lang3:3.6"
    const val zxing = "com.google.zxing:core:3.3.2"

    //leakcanary
    const val leakcanary = "com.squareup.leakcanary:leakcanary-android:2.4"

    //jetPack
    const val room_runtime = "androidx.room:room-runtime:2.2.5"
    const val room_compiler = "androidx.room:room-compiler:2.2.5"
    const val room_rxjava2 = "androidx.room:room-rxjava2:2.2.5"
    const val lifecycle_extensions = "android.arch.lifecycle:extensions:1.1.1"
    const val lifecycle_compiler = "android.arch.lifecycle:compiler:1.1.1"
    const val rxlifecycle = "com.trello.rxlifecycle3:rxlifecycle:3.1.0"
    const val rxlifecycle_components = "com.trello.rxlifecycle3:rxlifecycle-components:3.1.0"

    //Kotlin
    const val kotlinx_coroutines_core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
	...
}

4. Create a new versionplugin under VersionPlugin/src/main/java / package name / directory kt,
The Plugin interface is implemented as follows:

package com.controler.versionplugin

import org.gradle.api.Plugin
import org.gradle.api.Project

class VersionPlugin : Plugin<Project>{
    override fun apply(p0: Project) {

    }

    companion object{
        
    }
}

Note: when creating a VersionPlugin module, other useless resources generated can be deleted and only those needed can be reserved, as follows:

5. In settings Add includeBuild ("VersionPlugin") in gradle file. Note that includeBuild ~, Rebuild project
6. Later, you can use it in the gradle file you need to use, such as build. Com under app Gradle, add the following to the first line:

plugins {
    // Plug in ID defined in part 2
    id "com.controler.versionplugin"
}

// Defined dependent address
import com.controler.versionplugin.* 

Use the following

 

summary
1. Using groovy ext can't track dependencies, which is poor in readability and inconvenient for maintenance
2. Kotlin + BuildSrc is used to support two-way tracking, and the whole project will be rebuilt when relying on update
3. Using compositing builds supports one-way tracking, and the whole project will not be built when relying on updates

reference

Android ext
https://developer.android.com/studio/build/gradle-tips#configure-project-wide-properties
Kotlin + buildSrc for Better Gradle Dependency Management – Handstand Sam
Composing builds

Embrace Composing builds to improve Android compilation speed

Compositingbuildstest: use compositing builds to uniformly manage the three-party dependency sample code in the project, and write it in Java- Gitee.com


--------
Copyright notice: This is the original article of CSDN blogger "Jay, Xu", which follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this notice for reprint.
Original link: https://blog.csdn.net/Json_Jerry/article/details/112860914

Topics: C# Gradle Network Protocol p2p