Android Module 依赖关系的可视化实现

2,659 阅读3分钟

dependency-graph-plugin-task

这是一个生成 Module 依赖关系的有向无循环图可视化脚本

源码地址:github.com/mikeFei1000…

效果图

image.png

价值

  1. 可以快速获取最新依赖图,加速对项目结构的理解
  2. 定期输出依赖图,分析其中不合理的依赖并及时改进

用法

  1. 复制 projectDependencyGraph.gradle 文件到项目的根目录下
  2. 将插件添加进 app 的 build.gradle
apply from: "${project.rootProject.file('projectDependencyGraph.gradle')}"
  1. 执行命令
./gradlew projectDependencyGraph
  1. 结果文件的 output 目录 build/reports/dependency-graph/project.dot

如果本地安装了 graphviz 环境,插件会自动生成示意图,如果没有,就也需要利用在线工具,预览方式:project_digraph.dot的内容复制到在线工具预览 dreampuf.github.io/GraphvizOnl…

image.png

插件原理

  1. 通过遍历 project,分析当前模块依赖情况,收集 project的projectNameprojectDepedencyList
  2. 移除不需要的依赖,原则:当前节点的孩子队列,最短依赖,有可以被非最短依赖替代的,则删除最短依赖,例如
    1. app->module2> module5
    2. app->module5 保留a,删除b,改善模块依赖线条
  3. 根据收集的信息,输出markdown格式的文本信息,同时本地生成依赖图

依赖图

依赖图是一张有向无循环图,深度是指项目依赖图中模块与其每个叶节点之间的最大边数

深度

深度(Depths)考虑构建性能时特别有用,因为编辑器的构造顺序是根据明确的父子关系,即子节点必须在父节点之前构建

image.png

  • :lib-1:lib-2先于:screen-1
  • :lib-2先于:screen-2
  • :screen-1:screen-2先于:app

并行构建

单个模块构建始终是单线程完成的,但只要集合中没有模块依赖于该集合中的另一个模块,多个模块可以并行构建。在上图中,

  • :lib-1:lib-2可以并行构建
  • :lib-1:screen-2可以并行构建
  • :scren-1:screen-2可以并行构建 并行模块构建的最大数量由依赖图的结构和执行构建的机器上可用处理器内核的数量决定, 同时也要保证 gradle.properties 中有正确的开启 #开启并行编译
org.gradle.parallel=true
org.gradle.daemon=true
# 开启kotlin的增量和并行编译
kotlin.incremental=true
kotlin.incremental.java=true
kotlin.incremental.js=true
kotlin.caching.enabled=true

更好的结构

低深度值表示项目结构浅或平坦,意味着更快的构建更好的全方位可扩展性, 模块之间的耦合松散(或没有)。在完整构建中,低深度的项目可以很好地扩展,因为它们能够并行构建所有这些独立模块 下图左边是高“深度”项目,右边是低“深度”,应该提倡右边的依赖关系 image.png image.png

高深度的危害

  1. 高“深度”项目没有提供很多并行化的机会
  2. 影响增量构建的速度,中级模块的单个更改也会使一半项目的缓存构建无效

参考

  1. zhuanlan.zhihu.com/p/421286744
  2. github.com/JakeWharton…
  3. rbusarow.github.io/ModuleCheck…