一、前语

一个Android项目在不断地迭代之后,项目代码会变多,事务会膨胀,难免会去做一些组件化,插件化这些改造。就那组件化来说,我们需求剥离出各个事务模块,以及基础库,拆成一个个的组件,然后慢慢地由于代码变多,编译会时刻变得越来越长,然后影响开发调试的功率。然后我们或许会将组件源码以aar的方法引入,加速编译速度,然而我们在开发调试的时分,运用aar的方法不是很方便,所以需求一个aar和源码之间切换的方案,下面就简略说一下。

二、开始吧

1、没有Maven库房?

公司客户端不幸,没有自己的Maven库房,只有一台打包机,之前运用这台机器建立了Android项目的构建平台,看空间还有富裕,那就继续压榨它吧,再搭个maven库房吧,简略说下建立流程吧,我运用docker的方法装置的,docker的运用方法在/post/721920… ,/post/722999…都有提到。

1、拉取maven的镜像

docker pull sonatype/nexus3

镜像有许多,能够通过 docker search nexus 搜一下。

2、创立容器

docker run -d -p 8081:8081--name nexus  --restart=always sonatype/nexus3

然后浏览器输入: http://localhost:8081 即可翻开了,启动有点慢,所以显示打不开的时分多改写一下。

翻开后默许的登录账号:admin ,暗码需求去查看下

find / -name 'admin.password'

根据提示的途径查看

 cat xxx

Android组件化 aar/源码调试切换方案

3、创立总库

Android组件化 aar/源码调试切换方案

Android组件化 aar/源码调试切换方案

4、创立存储库

Android组件化 aar/源码调试切换方案

Android组件化 aar/源码调试切换方案

默许否则不能掩盖只能升版别,装备下可掩盖

Android组件化 aar/源码调试切换方案

获取终究的库房地址,下面需求

Android组件化 aar/源码调试切换方案

5、gradle中装备publish

group "com.example.aar.resource.plugin"
version "1.0.1"
publishing { //当时项目能够发布到本地文件夹中
    repositories {
        maven {
			//maven库房的地址 上图中有
            url = 'http://172.16.10.110:8081/repository/maven_test/'
            allowInsecureProtocol = true
            credentials {
                username 'admin'
                password 'qwertyu123'
            }
        }
    }
    publications {
        // Release 版别发布使命
        release(MavenPublication) {
            groupId group
            artifactId artifactId
            version version
            artifact("$buildDir/outputs/aar/child-release.aar")
        }
        // Debug 版别发布使命
        debug(MavenPublication) {
            groupId group
            artifactId artifactId
            version version
            artifact("$buildDir/outputs/aar/child-debug.aar")
        }
    }
}

在对应moudle的build.gradle中apply上述groovy即可 (apply from: ‘./publish.gradle’)

然后再命令行执行publish命令即可

// debug
./gradlew publishDebugPublicationToMavenRepository 
// release
./gradlew publishReleasePublicationToMavenRepository 
//一同
./gradlew publish

2、完成方法

装备文件:

{
  "libs": [
    {
      "projectName": "child",
      "packageName": "com.example.aar.resource.plugin",
      "use_aar": true,
      "version": "1.0.1"
    }
  ]
}

方法一 : 傻瓜式判别

//方法一
// 运用根目录的module_switch_config.json 来动态装备依靠库
dependencies {
    def switchConfig = getModuleSwitchConfig()
    def libs = switchConfig.libs
    println(switchConfig)
    libs.each { config ->
        println(config)
        if (config.use_aar) {
            println("运用aar")
            implementation("$config.packageName:$config.projectName:$config.version")
        } else {
            implementation project(":$config.projectName")
            println("运用本地")
        }
    }
}

方法二 运用substitute

// 方法二
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
    @Override
    void beforeEvaluate(Project projectObj) {
    }
    @Override
    void afterEvaluate(Project projectObj, ProjectState state) {
        projectObj.configurations.all { config ->
            config.resolutionStrategy.dependencySubstitution {
                def switchConfig = getModuleSwitchConfig()
                def libs = switchConfig.libs
                println(switchConfig)
                libs.each { lib ->
                    println(lib)
                    if (lib.use_aar) {
                        substitute project(":$lib.projectName")  using module("$lib.packageName:$lib.projectName:$lib.version")
                        println("运用aar")
                    } else {
                        substitute module("$lib.packageName:$lib.projectName:$lib.version") using project(":$lib.projectName")
                        println("运用本地")
                    }
                }
            }
        }
    }
})

在对应app的build.gradle中apply上述groovy即可 (apply from: ‘./../switch_aar.gradle’)

关于resolutionStrategy 和 dependencySubstitution以下是gpt-3.5的答案


resolutionStrategy API 中常用的函数和装备选项:

  • failOnVersionConflict(): 当产生版别抵触时,Gradle 将会停止构建并抛出反常。

  • preferProjectModules(): 假如存在多个版别的同一库,Gradle 将会挑选当时项目中的版别。

  • force(String... moduleIdentifiers): 强制运用指定的版别,忽略其他版别。能够传入一个或多个模块标识符,例如 'com.google.guava:guava:25.0'

  • latestVersion(): 运用最新版别的库。

  • highestVersion(): 运用最高版别的库。

  • lowestVersion(): 运用最低版别的库。

  • strictly(String... moduleIdentifiers): 强制运用指定版别,假如找不到则抛出反常。能够传入一个或多个模块标识符,例如 'com.google.guava:guava:25.0'

  • componentSelection(Action<? super ComponentSelection> action): 能够对每个依靠项进行个性化装备,比方排除某个依靠项或强制运用某个版别等。需求传入一个Action 方针,其间的参数 ComponentSelection 代表当时依靠项的组件挑选信息,您能够在 Action 中修正这些信息来完成个性化装备。例如:

dependencies {
    // 大局装备依靠处理战略
    resolutionStrategy {
        failOnVersionConflict()
        preferProjectModules()
        force 'com.google.guava:guava:25.0'
    }
    // 单个依靠项指定特定版别
    implementation('com.google.guava:guava:28.2-jre') {
        force = true
    }
    // 对每个依靠项进行个性化装备
    resolutionStrategy.componentSelection {
        if (it.candidate.version == '1.0') {
            it.reject('conflict with other dependency')
        }
        if (it.candidate.groupId == 'com.google.guava' && it.candidate.moduleId == 'guava') {
            it.useVersion('25.0')
        }
    }
}

总归,resolutionStrategy API 提供了多种选项来指定 Gradle 怎么处理构建过程中的依靠抵触,您能够根据实践情况挑选合适的选项来保证项目的稳定性和正确性。例如,您能够运用 failOnVersionConflict() 来保证一切依靠项的版别都能够正确匹配,或许运用 preferProjectModules() 来优先运用当时项目中的依靠项。假如您需求强制运用特定版别,能够运用 force(),假如您需求运用最新版别或许最高/最低版别,能够运用 latestVersion()highestVersion() 或许 lowestVersion()。假如您需求对某个依靠项进行特定的装备,例如排除某个依靠项或许强制运用某个版别,能够运用 componentSelection() 来完成个性化装备。

别的,需求留意的是 resolutionStrategy 中的选项会影响整个项目中的依靠处理战略,因而您需求慎重运用这些选项,保证它们能够契合您的实践需求。假如您需求对某个依靠项进行特定的装备,建议运用 componentSelection() 来完成个性化装备,这样能够更加灵活地控制依靠项的处理战略。

关于 dependencySubstitution


非常抱愧,我之前的答复中遗漏了 dependencySubstitution。下面是 dependencySubstitution API 的介绍:

dependencySubstitution 是 Gradle 构建东西中的一个 API,它能够用于替换依靠项。通过 dependencySubstitution,您能够将一个依靠项替换为另一个依靠项或许一个本地文件。

下面是 dependencySubstitution API 中常用的函数:

  • substitute(moduleNotation: String, target: Dependency):将指定依靠项替换为方针依靠项,其间 moduleNotation 是要替换的依靠项的模块标识符,例如 'com.google.guava:guava:28.2-jre'target 是方针依靠项,能够是另一个规范依靠项,也能够是一个本地文件依靠项。
  • substitute(moduleNotation: String, dependencyNotation: String):将指定依靠项替换为方针依靠项,其间 moduleNotation 是要替换的依靠项的模块标识符,例如 'com.google.guava:guava:28.2-jre'dependencyNotation 是方针依靠项的依靠符号符,例如 'com.google.guava:guava:25.0'
  • substitute(moduleNotation: String, file: File):将指定依靠项替换为本地文件,其间 moduleNotation 是要替换的依靠项的模块标识符,例如 'com.google.guava:guava:28.2-jre'file 是本地文件方针。
  • substitute(moduleNotation: Pattern, target: Dependency):将契合指定形式的依靠项替换为方针依靠项,其间 moduleNotation 是一个正则表达式形式,例如 ~/com.google.guava:.*/target 是方针依靠项,能够是另一个规范依靠项,也能够是一个本地文件依靠项。
  • substitute(moduleNotation: Pattern, dependencyNotation: String):将契合指定形式的依靠项替换为方针依靠项,其间 moduleNotation 是一个正则表达式形式,例如 ~/com.google.guava:.*/dependencyNotation 是方针依靠项的依靠符号符,例如 'com.google.guava:guava:25.0'
  • substitute(moduleNotation: Pattern, file: File):将契合指定形式的依靠项替换为本地文件,其间 moduleNotation 是一个正则表达式形式,例如 ~/com.google.guava:.*/file 是本地文件方针。

您能够在 dependencies 块中运用 dependencySubstitution 来大局装备依靠项替换规矩,例如:

dependencies {
    // 大局装备依靠项替换规矩
    dependencySubstitution {
        substitute(module('com.google.guava:guava'), 'com.google.guava:guava:25.0')
        substitute(module('com.example:lib'), files('/path/to/local/lib.jar'))
    }
}

总归,dependencySubstitution 能够帮助您完成依靠项的替换,然后满意特定的需求。例如,您能够将某个依靠项替换为本地文件,以完成对某个库的修正或许调试。

三、终究

arr和源码切换的方法有许多,也能够不用substitute,自己定义规矩,但终究离不来gradle提供的api,第一种需求在一切的有依靠装备的当地导入上述gradle文件,第二种导入一次就够了,终究安利个好玩链接github.com/xtekky/gpt4… 你懂的,里面有布置好的链接,也能够按照文档自己布置在本地就是有点丑

Android组件化 aar/源码调试切换方案