Android的奇技淫巧—多个Project代码同时引入

背景

从开始学习编程时,老师就告诉我们设计模式、MVC等在编程中非常重要,所以一定要努力学习。在项目设计的时候,为了更好地解耦,我们往往会将每一个小模块都设计到了独立的 module 里面,但是这样子虽然做了拆分,却并不能很好地在各个项目中重用它们。因此笔者做了一个更加严格拆分,每一个library都会放在独立的project中,这样就可以更好地在不同的项目里重用library。不仅如此,我们在打开独立的project时,Android Studio 会运行的更流畅。

每一个library在使用的时候都会被打包成aar,上传到公司内部的maven服务器,如此进行依赖就可以避免基础库遭到乱改。

但是使用这种方式,并不利于源码的阅读。因此我们需要将不同的项目引入到同一个工种中进行加载。

引入工程

首先我们来看一下,使用module的时候,是如何引入的,如下:

include ":demo", ":common-android"

现在我们需要把外部工程的 module 也引入进来。要怎么做呢?

如下:

  1. 使用Android Studio打开作为主工程的项目

  2. 手动打开主工程项目根目录下的settings.gradle,添加module的依赖进去

    include ":toolkit"
  3. 给引入的module指定projectDir的路径(项目文件的真实路径,建议使用相对路径)

    project(":toolkit").projectDir = new File("../toolkit_lib/toolkit")

    其中,../toolkit_lib为 toolkit 的项目目录,这个目录下是一个完整的AS项目,可以直接打开。

项目依赖处理

按照上面的方式,我们可以在一个项目中查看所有的module的源代码,但是,在独立项目中,没有源代码,为解决依赖问题,我们会将每一个module都上传到maven服务器,使用路径地址来进行项目依赖管理。

那么,问题来了。我们将所有的源代码都引入到了一个项目中,但是代码间的跳转还是使用的maven中下载下来的代码库。

为了解决这个问题,我们可以定义一个变量来处理,判断当前module是否是在独立的项目中,如果是在独立的项目中,使用maven库的依赖,如果是以代码的形式引入整个项目,则直接使用代码库的依赖。

  • 定义变量
    在每一个独立的项目中,在gradle.properties文件中添加isAlone属性,如下:

    isAlone=true
  • 读取isAlone的值

    build.gradle文件中,读取isAlone属性,如果为true,依赖maven中的library, 反之依赖project中的。代码如下:

    def isAlone = "true" // 默认值为true
    // 判断是否存在isAlone属性,如果存在,读取他的值
    if (project.hasProperty("isAlone")) { 
    isAlone = project.isAlone
    }
    // 如果是独立项目,使用maven的引用,反之使用project
    if (isAlone == "true") {
    project.dependencies.add("compile", "com.knero.test:toolkit:1.0.0@aar")
    } else {
    project.dependencies.add("compile", project(':toolkit'))
    }

    在添加依赖的时候,可以使用代码add的方式,当然也可以直接将不同的dependences放在不同的文件中,然后分情况依赖不同的文件,如下:

    if (isAlone == "true") {
        apply from: 'dependencies_sdk.gradle'
    } else {
        apply from: 'dependencies_sdk_proj.gradle'
    }

    不仅是依赖可以通过groovy代码进行添加,Android的其它属性也可以添加,Demo如下:

    android.sourceSets.main.res.srcDirs = ['res', 'otherRes']
    android.sourceSets.main.jniLibs.srcDirs = ['libs', 'otherLibs']
    android.sourceSets.main.assets.srcDirs = ['assets', 'otherAssets']

到现在,我们的问题基本解决,但是我追求完美,还一个小瑕疵需要解决。

多项目引入的VCS处理

Android Studio有一个VCS的模块,他可以快速的在AS中处理git相关的逻辑。我都会使用他的Modify/New/Rename/Delete/Revert 等功能。但是AS默认只能处理一个项目。所以,导致我们引入的其它Project中的Module不支持git的特点,使用起来非常的不方便。经过一系列的查找,终于找到解决方案。

一个intellij idea项目,在其根目录下都有一个.idea的文件夹,这个里面存储着整个项目的配置文件,当然也包括git的, 文件名为vcs.xml, 默认内容如下:


<project version="4">
    <component name="VcsDirectoryMappings">
        <mapping directory="$PROJECT_DIR$" vcs="Git" />
    component>
project>

当然,我们需要更改这个文件,将我们的toolkit_lib文件夹加入到里面,修改过后如下:


<project version="4">
    <component name="VcsDirectoryMappings">
        <mapping directory="$PROJECT_DIR$" vcs="Git" />
        <mapping directory="$PROJECT_DIR$/../toolkit_lib" vcs="Git" />
    component>
project>

PS: toolkit_lib 和当前引入的项目在同一个文件夹下面,所以使用PROJECT_DIR相对路径,来指定项目目录。当然,这个地方的directory, 你也可以使用绝对路径来指定。

依赖引入的最佳实践

我们有多个项目需要引入,但是部分项目,没有修改的需求,并没有要把项目引入的需求。所以,使用一个变量,来管理所有的项目,使用起来,略显灵活度不够。所以,我们将每一个项目按照单独properties来读取其状态,当其中一个项目的dependencies要使用maven,我们只需要将其对应的变量值设置为true或者删除掉。读取属性的代码如下:

def isAloneProject = "true"
def propertiesName = "${project.name}Alone"
if (project.hasProperty(propertiesName)) {
    isAloneProject = project.property(propertiesName)
}
if (isAloneProject == "true") {
    // dependencies maven path.
} else {
    // dependencies project path.
}

当作为module引入的时候,只需要在主Project中的gradle.properties文件里面加入对应值。

toolkitAlone=false

传送门

欢迎关注我的公众号,一起交流技术事。

Android的奇技淫巧—多个Project代码同时引入_第1张图片

你可能感兴趣的:(Android的奇技淫巧)