Android - 依赖统一管理

2,928 阅读5分钟

前言

前段时间自己在搭建组件化框架时候遇到了多人协作 Moudle 版本依赖冲突以及重复导包和同一个包导入不同版本的情况,针对这个问题对依赖统一这块做了一次比较详细的学习和总结

目前Android依赖统一管理的方式有以下几种方式,接下来我们一起慢慢分析一下各种方式优缺点

    1. groovy ext扩展函数(也有称之为:"循环优化")
    1. kotlin+buildSrc
    1. composing builds
    1. catalog
    1. 自定义插件+includeBuild

Groovy ext扩展函数

这种方式可能是大家最开始或者说是比较常见的一种依赖配置方式: iShot2021-12-02 15.17.09.png

示例代码

然后在项目根build.gradle(即root路径下)

apply from:"config.gradle"

引入的方式有两种一种是循环遍历:

iShot2021-12-03 10.26.55.png

iShot2021-12-03 10.32.12.png

总结:

优点:

1:后续添加依赖不需要改动build.gradle,直接在config.gradle

2:精简了build.gradle的长度

缺点:

1:不支持代码提醒

2:不支持点击跳转

3:多moudle 开发时,不同module的依赖需要ctrl+c/v 导致开发的效率降低

kotlin+buildSrc

buildSrc

The directory buildSrc is treated as an included build. Upon discovery of the directory, Gradle automatically compiles and tests this code and puts it in the classpath of your build script. For multi-project builds there can be only one buildSrc directory, which has to sit in the root project directory. buildSrc should be preferred over script plugins as it is easier to maintain, refactor and test the code.

这是来自gradle官方文档对buildSrc的解释:

当运行 Gradle 时会检查项目中是否存在一个名为 buildSrc 的目录。然后 Gradle 会自动编译并测试这段代码,并将其放入构建脚本的类路径中, 对于多项目构建,只能有一个 buildSrc 目录,该目录必须位于根项目目录中, buildSrc 是 Gradle 项目根目录下的一个目录,它可以包含我们的构建逻辑,与脚本插件相比,buildSrc 应该是首选,因为它更易于维护、重构和测试代码

通过上面的介绍,大家或许对buildsrc 有一定理解了,那么我们就看下他怎么和kotlin一起使用达到项目统一依赖管理的

iShot2021-12-03 13.44.50.png

如上图所示我们首先创建一个名为buildSrc的module,gradle 构建的时候会先检查工程中是否有buildSrc命名的目录然后会自动编译和测试这段代码并写入到构建脚本的类路径中,所以无需在setting.gradle 做任何配置有关buildSrc的配置信息

官方的配置信息

iShot2021-12-03 14.19.27.png

iShot2021-12-03 14.21.33.png

这是我的项目中配置信息

这种方式管理依赖优点和缺点如下:

优点:

  • 1:但这种方式支持IDE,输入代码会有提示,会自动完成,所以非常推荐使用这种方式来管理项目中的依赖包

  • 2:支持 AndroidStudio 单击跳转

  • 3:buildSrc是Android默认插件,全局只有这一个地方可以修改

缺点:

来自gradle文档

A change in buildSrc causes the whole project to become out-of-date. Thus, when making small incremental changes, the --no-rebuild command-line option is often helpful to get faster feedback. Remember to run a full build regularly or at least when you’re done, though.

更改buildSrc会导致整个项目过时。因此,在进行小的增量更改时,--no-rebuild命令行选项通常有助于获得更快的反馈。不过,请记住定期或至少在完成后运行完整构建。

从官网的解释我们可以得出结论:

buildSrc 是对全局的所有 module 的配置依赖更新会重新构建整个项目,项目越大,重新构建的时间就越长,造成不必要的时间浪费。

阅读到这里我们可能会思考那么有没有一种方式是在部分module 需要修改依赖版本的时候而不会重新构建整个项目的方式呢,探索极致是每一个研发人员毕生所追求的,那么includeBuild这种方式应运而生

composing builds

那么我们开始一步一步实现这种方式:

1:首先创建一个library 的module <对于使用kotlin 或者 java>就要看自己的比较中意哪种语言喽

iShot2021-12-03 14.46.44.png

2:就是在library 配置插件等信息

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

buildscript {
    repositories {
        // https://developer.aliyun.com/mvn/guide
        //todo error:"Using insecure protocols with repositories, without explicit opt-in,"
        google()
        mavenCentral()
        maven { url 'https://maven.aliyun.com/repository/public' }
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
    }

    dependencies {
        // 因为使用的 Kotlin 需要需要添加 Kotlin 插件
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
    }
}




repositories {
    // 需要添加 jcenter 否则会提示找不到 gradlePlugin
    repositories {
        google()
        mavenCentral()
        maven { url 'https://maven.aliyun.com/repository/public' }
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
    }

}

dependencies {
    implementation gradleApi()
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}


compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

gradlePlugin{
    plugins {
        version{
            // 在 app 模块需要通过 id 引用这个插件
            id = 'com.bimromatic.version.plugin'
            // 实现这个插件的类的路径
            implementationClass = 'com.bimromatic.plugin.VersionPlugin'
        }
    }
}

3:在项目路径下建立一个在.gradle 配置的类名实现Plugin 这个接口

/*
 * Copyright 2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.gradle.api;

/**
 * <p>A <code>Plugin</code> represents an extension to Gradle. A plugin applies some configuration to a target object.
 * Usually, this target object is a {@link org.gradle.api.Project}, but plugins can be applied to any type of
 * objects.</p>
 *
 * @param <T> The type of object which this plugin can configure.
 */
public interface Plugin<T> {
    /**
     * Apply this plugin to the given target object.
     *
     * @param target The target object
     */
    void apply(T target);
}

4:在settings.gradle添加

iShot2021-12-03 15.01.56.png

5:在需要用的地方添加插件名

iShot2021-12-03 15.03.33.png

详细配置请移步我们的项目查看

因为时间的原因,这次项目管理依赖就讲到这里,后续会把google在孵化器期 Catalog统一配置依赖版本 讲解一下,然后我们再把各种依赖管理方式用在编辑器跑一下试试看看那种方式构建速度最快。

如果你们觉得写得不错的随手给我点个关注,后期会持续做移动端技术文章的分享,或者给我的github 点个start 后期会上传一些干货。

对了如果文章中有讲的什么不对的地方咱们评论区见,或者提上你们宝贵的issue