Speedup:专为项目下Library project过多所设计的加速插件

背景

随着app的持续迭代更新,新功能的持续集成等缘由。项目中的library project愈来愈多。android

特别是最近一两年来。流行起来了组件化,这更是直接增长了不少的本地library project的数量。致使每次须要打包apk运行时,都会须要对全部module都进行再次编译。严重影响打包速度。git

加速插件简介

Speedup是一款专用于对多module环境下进行打包加速的gradle插件。主要依赖的基本原理有两个:github

  1. 动态依赖替换
  2. 打包任务特性

插件地址

github.com/JumeiRdGrou…shell

动态依赖替换

咱们先来看看常规多module环境下的打包流程:api

从上图能够看到。每次打包的时候。都会通过如下几个步骤:bash

  1. 对依赖的module进行进行打包编译,生成各自library的aar依赖。
  2. 对aar依赖进行合并。包括classes.dex的合并、资源合并等。
  3. 将合并后的文件、资源进行打包,生成apk。

而若是。咱们使用maven依赖的方式进行依赖的话。编译流程就会优化成下图所示的方式:网络

能够看到。与上面直接使用module依赖的方式相比:使用Maven仓库依赖的方式,因为maven仓库中提供的直接就是已打包好的aar依赖,因此直接干掉了module -> aar打包编译的过程,起到了加速编译的做用!并发

因此,如今咱们就能够得出第一个结论:使用maven依赖比使用module依赖更快速!app

因此这个时候。不少人的常规作法就是。想办法将这些module依赖的library,编译打包发布到各自的远程中央仓库中去,这样就能避免每次运行的时候都去进行额外编译,从而节省时间了。maven

可是这种作法存在几个问题:

  1. 绝大部分library并不稳定。须要常常修改使用,若放到远程仓库,修改起来很麻烦
  2. 远程仓库的version版本号惟一,每次进行修改后都会须要更新升级版本号再发布。多人协做时容易形成混乱且也不容易维护

因此将module打包发布到远程仓库的作法,并不可取!

如今咱们来考虑一下,若是将仓库设置在本地会怎样?也就是说使用本地maven仓库进行依赖管理。

咱们来列举一下这里使用本地依赖的优势:

  • 本地仓库中version不惟一

    便可以作到同版本覆盖发布,修改代码后直接从新发布便可,不须要提高version版本。这也正是远程仓库所作不到的。可避免频繁升级改动。

  • 本地仓库不与网络打交道

    读取依赖更快速。事实上,远程仓库中所依赖的库,也是先存放到本地仓库中去再进行读取的。

能够看到,使用本地仓库,能够完美的解决频繁发包的问题!由于若是你的library不须要频繁修改的话,你确定也早就已经把它单独拆出去放远程仓库中去了~

因此咱们只要解决依赖不统一的问题。那么这个加速方案就算是完全打通了!

打包任务特性

打包任务这里特指的assembleXXX任务。这个任务相信你们平时也见过无数次了。

此任务是由android插件所提供的,编译、合并、打包一条龙的总线任务。平时咱们点击运行按钮、打包apk时。也是经过的调用此任务进行打包。打包后经过内置的adb命令将apk发送到手机并执行安装。

这个任务有个很重要的特性。这里我称之为按需加载特性

打个比方:假如咱们使用的组件化开发模式,项目依赖链以下图所示:

上图所示的依赖链,对组件化不熟的可能会比较懵逼。对组件化有兴趣的能够去这里了解一下组件化的项目结构:聚美组件化实践之路

这里有三个可运行的壳工程。其各自壳工程的依赖链以下:

  1. [app shell 1] -> [component 1] -> [base library]
  2. [app shell 2] -> [component 2] -> [base library]
  3. [Main app] -> [component 1] & [component 2] -> [base library]

按需加载特性是指:在进行打包任务过程当中,打包任务只会触发当前自身依赖链中的module进行编译。而不会对别的非自身依赖链中的module进行编译。

因此,当你运行app shell1的时候。这个时候会参与打包编译的就是[app shell 1]、[component 1]、[base library]这三个module. 这就是按需加载特性

原理

基于以上分析,我创建了此Speedup插件。利用gradle脚本,方便的进行本地aar打包发布,并经过对打包任务流程进行监听,动态的将module依赖替换为本地仓库中的maven依赖。

流程图

这里我画了个简单的流程图。便于直观的理解此gradle插件的运行机制。

特性

  • 原理简单:整个插件由三个文件组成,并有详细注释,很容易理解
  • 配置简单:简单得出乎你意料!
  • 不一样机器配置独享,不冲突:
  • 兼容性好:实现逻辑依赖最简单的api。最大程度下降gradle版本升级时sdk改动形成的影响。

使用方式

依赖配置

在项目根目录下添加依赖并添加应用插件

buildscript {
    repositories {
        // 添加jitpack仓库地址
        maven { url "https://jitpack.io" }
    }
    dependencies {
        // 添加插件依赖
        classpath "com.github.yjfnypeu:Speedup:0.9"
    }
}
// 应用插件
apply plugin: 'speedup'
复制代码

属性配置

Speedup支持配置三种属性,均配置于项目根目录下的local.properties文件中。

  • speedup.enable:

    是否激活speedup插件。默认为false,即不激活。这样作的目的是为了使得在发版机器上进行打包apk时。自动忽略speedup插件。进行全量编译

  • localRepo:

    本地maven仓库的地址。默认为项目根目录下的_repo文件夹。若你须要使用别的地址。在此配置个本地地址便可

  • excludeModules:

    因为咱们开发的业务线的不一样。不少时候咱们是须要对部分的module每次都进行即时编译的:好比说如今正在作的功能。是须要对某个lib进行频繁修改的。因此这个时候。就须要使用此属性。指定此lib不须要进行加速。那么每次运行时。都会对此lib进行编译。

把全部属性全放置于local.properties中,出于如下几点考虑:

  • 每一个人所须要使用的配置方案不同,放于local文件中,能够起到配置独立的做用。
  • 发版apk不使用加速方案。通常打包发版apk的均运行在独立的机器上.

配置示例

github上我提供了一个组件化demo地址, 此demo中有添加此插件配置使用。如下内容建议结合demo进行查看。

Android组件化demo展现

因为本地配置是放置于local.properties文件当中。因此默认依赖下来是没有开启激活此插件的。能够参考下方的配置:放入自身的local.properties中去。

speedup.enable=true
# 当须要排除多个module时,中间用英文的逗号隔开
excludeModules=:usercenter:componentusercenter
复制代码

当配置speedup.enable为true,而且同步完成以后。你就能够在gradle任务列表中发现一组speedup任务:

能够看到。speedup任务组中。含有大量的uploadXXX任务提供使用。这些任务都是在同步时根据各个library module自动生成的上传任务。主要目的是将本地的library module方便的进行打包、编译。并发布到本地的仓库中去。提供使用。

当你使用upload进行本地打包发布后,你就能够在项目根目录下的_repo文件夹下找到对应的打包出来的aar:

而后,你能够试试直接运行。而且观察右下角的Gradle Console控制台输出日志。注意看全部执行的任务列表。就会发现:执行的gradle任务明显减小了,而且被打包到本地中的module。并无被再次进行编译。

这是由于已经在运行时。动态的将对应的module替换为使用本地仓库中的aar地址了。

以上便是此插件的整个用法示例。能够总结为如下几步:

  1. 添加依赖、配置
  2. 执行upload任务进行本地发布
  3. 直接运行。

upload任务列表说明

Speedup插件任务中,很重要的一点便是生成的upload任务列表了。此upload任务主要分为三类:

  1. uploadAll

    做用:用于对项目中全部的library(除了excludeModules所指定排除的module)进行打包发布。此任务默认将会对项目下全部的module执行clean操做。因此能够保证打包出来的aar是不受数据污染的

    使用场景:在进行分支切换后、或者进行合并代码后。此时不少module的数据都有修改。可使用此任务一次性所有从新打包上传。

  2. uploadForClean

    做用:用于触发项目下全部module的clean任务。将其build文件夹删除。避免打包时出现数据污染。

    与AS自带的clean任务不一样。自带的clean任务附带了不少额外的任务,因此每次clean会很慢。而uploadForClean。只会触发全部module自身的clean任务,对自身的build文件夹进行删除,并没有其余额外操做。这样clean的速度会获得很大提高。

    此任务通常来讲外部不须要直接使用。主要是内部直接提供给uploadAll进行使用

  3. uploadXXX

    做用:用于对指定的module进行从新打包发布。好比uploadbaselib。此任务表明对baselib从新进行打包发布。

相关文章
相关标签/搜索