当前位置:首页 » 《关注互联网》 » 正文

组件化下如何优雅进行本地调试,即aar依赖与module依赖动态切换_Android架构交流群:519844232

26 人参与  2021年09月07日 12:23  分类 : 《关注互联网》  评论

点击全文阅读


在组件化开发的时候,会面临的一个问题就是组件的调试。

即组件和主工程不在同一个工程目录下,主工程对组件的依赖,是通过依赖组件发布的aar包的方式引入。当组件开发了新的功能,就会发布一个新的 aar 包,并在主工程引入。

但如果这种方式带来的问题就是,如果组件有bug或者需要调试的时候,就会带来不便。具体来说就是,如果改一个问题,就发布一个组件的 aar 包,然后在主工程验证问题是否被修复成功。 这样就会频繁的发布 aar 包,而且调试的效率也低,那有没有办法在开发阶段,直接引用 组件module,而不使用组件的 aar 包呢?答案当然是有的,下面就来介绍一下具体的实现方案。

准备工作:

假设主工程路径:/Users/mei/WorkSpace/AndroidProjects/TestModuleDep

组件工程路径:/Users/mei/WorkSpace/AndroidProjects/module-user/user

组件的maven路径:com.mei.module:user:1.0.0

在主工程的 build.gradle 文件中,引入 user 组件:

dependencies {
    implementation 'com.mei.module:user:1.0.0'
}

一、组件module(源码)依赖方式

从上面的介绍可以知道,主工程 依赖 user 组件,是通过依赖 user 组件的 aar 包的方式进行的。如果想本地调试的话,可以改成依赖组件module 的方式。具体操作如下:

1、include 组件 module

在主工程的 settings.gradle 文件中,把 组件module 加入编译,即 include 组件module。组件跟主工程不在同一个工程目录下,所以,组件module 的 include 方式也有所不同:

include ":user"
project(":user").projectDir = file("/Users/mei/WorkSpace/AndroidProjects/module-user/user")

如上代码所示,在 主工程的 settings.gradle 文件中,增加上述代码,就可以把 组件module 以 include 的方式,加入到主工程中。

2、依赖组件module

在主工程的 app module 中,依赖组件module,即在 app 的 build.gradle 文件中,依赖组件module,同时,把组件的 aar 包依赖给注释掉:

dependencies {
    // implementation 'com.mei.module:user:1.0.0'
    implementation project(':user') // 以 组件module 的方式依赖组件
}

经过上面两步操作,就可以直接依赖组件的源码,而不是组件的 aar 包了,调试起来就非常方便了,不用每次改动都发布一个aar 包。

通过上面的方式,是可以源码依赖的问题,但每次需要调试的时候都这样去改的话,就显得非常的麻烦,还需要把 aar 依赖的方式给注释掉,万一不小心提交了代码,就有可能导致远程无法打包的问题。

那有没有什么方式是在 开发的时候使用 module 依赖,而不改变app 的gradle 文件呢?下面就介绍一种 aar依赖 与 源码依赖快速切换的方式。

二、aar依赖 与 源码依赖 快速切换

在主工程的 build.gradle 文件中,增加如下代码:

allprojects {// 所有组件都添加
    configurations.all {
        resolutionStrategy {
            dependencySubstitution {
            		// module,groupId:artifactId
            		// project,组件module 名称
                substitute module( "com.mei.module:user") with project(':user')
            }
        }
    }
}

上述代码的意思是,以 module 代替 aar 包,则在编译工程的时候,只会把 module 的代码加入编译,而 aar 包的代码不会加入编译。

当然,也可以只在 app 的build.gradle 文件中,加入上述代码,这个时候就可以不用调用 allprojects 方法了,如:

configurations.all {
  resolutionStrategy {
      dependencySubstitution {
          // module,groupId:artifactId
          // project,组件module 名称
          substitute module( "com.mei.module:user") with project(':user') // 注释1 
      }
  }
}

如果不想使用 module 依赖,就可以 把 注释1 的代码,给注释掉,就可以接着使用 aar依赖了。

三、组件依赖封装

经过 二、aar依赖 与 源码依赖 快速切换 的操作之后,我们可以不用 注释掉组件的 aar 依赖,就可以实现 aar依赖 与 module依赖的 快速切换,但还是需要去修改主工程的 settings.gradle 文件和 build.gradle 文件,还是会存在误提交的问题。

如果我把 所有的操作,都放到一个 gradle 文件中,只在主工程的 settings.gradle 文件中,引入这个 gradle 文件,就可以实现上面所有的操作,并且在找不到这个文件的时候,也不会导致编译流程失败,不就可以解决误提交的问题吗?

下面就来看看具体是如何封装的。

1、在 module 工程中,增加 module 依赖文件

在 module 工程中,增加 user_dependency.gradle 文件(完整路径:/Users/mei/WorkSpace/AndroidProjects/module-user/user_dependency.gradle),在这个文件中,实现 组件module 的 引入和 与aar依赖的动态切换功能。注意,这个文件可以不用加入到 git 管理。

1-1、组件module 依赖
include ":user"
project(":user").projectDir = file("/Users/mei/WorkSpace/AndroidProjects/module-user/user")
1-2、aar 依赖 与 组件module 依赖的动态切换

user_dependency.gradle 文件中,增加如下监听:

gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {

    @Override
    void beforeEvaluate(Project projectObj) {
        try {
          	// 增加扩展属性
            if (!projectObj.rootProject.extensions.hasProperty("kotlin_version")) {
                projectObj.rootProject.extensions.add("kotlin_version", "1.4.32")
            }
        } catch (Exception e) {
            e.printStackTrace()
        }
      	// 应用组件工程的全局配置文件
        projectObj.rootProject.apply from: "/Users/mei/WorkSpace/AndroidProjects/module-user/mavenConfig.gradle"

        println "beforeEvaluate project.configurations=${projectObj.configurations}"
    }

    @Override
    void afterEvaluate(Project projectObj, ProjectState state) {
        println "project name is $projectObj"
        println "afterEvaluate project.configurations=${projectObj.configurations}"
        if (projectObj.name != "app") {
            return
        }
      	// 切换 aar依赖 与 组件module 依赖
        projectObj.configurations.all { Configuration ->
            resolutionStrategy {
                dependencySubstitution {
                    substitute module( "com.mei.module:user") with project(':user')
                }
            }
        }
    }
})
  1. 给 gradle 对象,增加 ProjectEvaluationListener 监听事件
  2. 在 ProjectEvaluationListener 的 beforeEvaluate 方法中,增加一些组件需要依赖的额外配置,如果没有,可以不用添加。
  3. 在 ProjectEvaluationListener 的 afterEvaluate 方法中,给指定的工程对象,增加配置信息,如:给 app 工程,增加动态切换 aar依赖 和 module 依赖的 配置。

注意:

  • 要把 afterEvaluate 的 Project 参数重新命名,否则在 dependencySubstitution 闭包中,调用 project() 方法会报错。
  • 只能在 ProjectEvaluationListener 的 afterEvaluate 方法 给工程增加配置信息,因为在 afterEvaluate 方法中,工程的configurations 配置对象不为空,而在 beforeEvaluate 方法中,工程的 configurations 对象是一个空对象,从而也无法 增加配置信息。
1-3、完整的 user_dependency.gradle 代码如下:
// 1. include 组件 module ,注意,使用绝对路径
include ":user"
project(":user").projectDir = file("/Users/mei/WorkSpace/AndroidProjects/module-user/user")

// 2. aar依赖 与 module依赖 动态切换
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {

    @Override
    void beforeEvaluate(Project projectObj) {
        try {
          	// 增加扩展属性
            if (!projectObj.rootProject.extensions.hasProperty("kotlin_version")) {
                projectObj.rootProject.extensions.add("kotlin_version", "1.4.32")
            }
        } catch (Exception e) {
            e.printStackTrace()
        }
      	// 应用组件工程的全局配置文件
        projectObj.rootProject.apply from: "/Users/mei/WorkSpace/AndroidProjects/module-user/mavenConfig.gradle"

        println "beforeEvaluate project.configurations=${projectObj.configurations}"
    }

    @Override
    void afterEvaluate(Project projectObj, ProjectState state) {
        println "project name is $projectObj"
        println "afterEvaluate project.configurations=${projectObj.configurations}"
        if (projectObj.name != "app") {
            return
        }
      	// 切换 aar依赖 与 组件module 依赖
        projectObj.configurations.all { Configuration ->
            resolutionStrategy {
                dependencySubstitution {
                    substitute module( "com.mei.module:user") with project(':user')
                }
            }
        }
    }
})

2、在主工程的 settings.gradle 文件中,应用依赖文件

在主工程的 settings.gradle 文件中,应用 user_dependency.gradle 文件:

include ":app"

try {
    apply from:"/Users/mei/WorkSpace/AndroidProjects/module-user/user_dependency.gradle"
} catch (Exception e) {
    e.printStackTrace()
}

通过绝对路径的方式,应用 user_dependency.gradle 文件。这里增加 try catch 的目的是,即使找不到 user_dependency.gradle 文件的时候,也不会影响整体的编译流程。即 哪怕引用不到 组件module 还可以使用 aar 依赖。

这样,只需要修改主工程的 settings.gradle 文件,就可以实现 组件 aar依赖 与 组件module 的动态切换,而且 settings.gradle 的修改也可以提交,不会影响线上的的打包流程。

当debug的 时候,如果想用 aar依赖的方式,可以把 应用 user_dependency.gradle 文件的代码注释掉就可以了。
当然,也可以在 user_dependency.gradle 文件中,增加一个 开关,表示是否使用 module 依赖,从而控制 module 与 aar包 的动态切换操作。

如:

.... 

def useModule = true

// 2. aar依赖 与 module依赖 动态切换
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {

    @Override
    void beforeEvaluate(Project projectObj) {
     	.... 
    }

    @Override
    void afterEvaluate(Project projectObj, ProjectState state) {
        if (projectObj.name != "app") {
            return
        }
      	// 切换 aar依赖 与 组件module 依赖
        projectObj.configurations.all { Configuration ->
            resolutionStrategy {
                dependencySubstitution {
                		if(useModule){ // 只有开关打开的时候,才使用 module 依赖
                				substitute module( "com.mei.module:user") with project(':user')
                		}
                }
            }
        }
    }
})

思考与扩展:

上面的操作,是否可以封装到一个插件中,这样只需要在 主工程中 提供一份 配置信息,就可以动态控制 aar依赖 与 组件module 依赖的动态切换。本地调试也会更加的方便快捷。


点击全文阅读


本文链接:http://zhangshiyu.com/post/27237.html

组件  依赖  工程  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1