Android studio 工程的 module 依赖关系图绘制 、 Android Module 依赖关系的可视化实现

整体步骤:

  • 1、利用gradle脚本生成dot;

  • 2、利用graphviz将dot可视化转为图片

利用gradle脚本生成dot

下载projectDependencyGraph.gradle脚本

下载 projectDependencyGraph.gradle ,放在项目根目录,

源码如下:

java 复制代码
task projectDependencyGraph {
    doLast {
        def dot = new File(rootProject.buildDir, 'reports/dependency-graph/project.dot')
        dot.parentFile.mkdirs()
        dot.delete()

        dot << 'digraph {\n'
        dot << "  graph [label=\"${rootProject.name}\\n \",labelloc=t,fontsize=30,ranksep=1.4];\n"
        dot << '  node [style=filled, fillcolor="#bbbbbb"];\n'
        dot << '  rankdir=TB;\n'

        def rootProjects = []
        def queue = [rootProject]
        while (!queue.isEmpty()) {
            def project = queue.remove(0)
            rootProjects.add(project)
            queue.addAll(project.childProjects.values())
        }

        def projects = new LinkedHashSet<Project>()
        def dependencies = new LinkedHashMap<Tuple2<Project, Project>, List<String>>()
        def multiplatformProjects = []
        def jsProjects = []
        def androidProjects = []
        def javaProjects = []

        queue = [rootProject]
        while (!queue.isEmpty()) {
            def project = queue.remove(0)
            queue.addAll(project.childProjects.values())

            if (project.plugins.hasPlugin('org.jetbrains.kotlin.multiplatform')) {
                multiplatformProjects.add(project)
            }
            if (project.plugins.hasPlugin('org.jetbrains.kotlin.js')) {
                jsProjects.add(project)
            }
            if (project.plugins.hasPlugin('com.android.library') || project.plugins.hasPlugin('com.android.application')) {
                androidProjects.add(project)
            }
            if (project.plugins.hasPlugin('java-library') || project.plugins.hasPlugin('java')) {
                javaProjects.add(project)
            }

            project.configurations.all { config ->
                config.dependencies
                        .withType(ProjectDependency)
                        .collect { it.dependencyProject }
                        .each { dependency ->
                            projects.add(project)
                            projects.add(dependency)
                            rootProjects.remove(dependency)

                            def graphKey = new Tuple2<Project, Project>(project, dependency)
                            def traits = dependencies.computeIfAbsent(graphKey) { new ArrayList<String>() }

                            if (config.name.toLowerCase().endsWith('implementation')) {
                                traits.add('style=dotted')
                            }
                        }
            }
        }

        projects = projects.sort { it.path }

        dot << '\n  # Projects\n\n'
        for (project in projects) {
            def traits = []

            if (rootProjects.contains(project)) {
                traits.add('shape=box')
            }

            if (multiplatformProjects.contains(project)) {
                traits.add('fillcolor="#ffd2b3"')
            } else if (jsProjects.contains(project)) {
                traits.add('fillcolor="#ffffba"')
            } else if (androidProjects.contains(project)) {
                traits.add('fillcolor="#baffc9"')
            } else if (javaProjects.contains(project)) {
                traits.add('fillcolor="#ffb3ba"')
            } else {
                traits.add('fillcolor="#eeeeee"')
            }

            dot << "  \"${project.path}\" [${traits.join(", ")}];\n"
        }

        dot << '\n  {rank = same;'
        for (project in projects) {
            if (rootProjects.contains(project)) {
                dot << " \"${project.path}\";"
            }
        }
        dot << '}\n'

        dot << '\n  # Dependencies\n\n'
        dependencies.forEach { key, traits ->
            dot << "  \"${key.first.path}\" -> \"${key.second.path}\""
            if (!traits.isEmpty()) {
                dot << " [${traits.join(", ")}]"
            }
            dot << '\n'
        }

        dot << '}\n'

//        def p = 'dot -Tpng -O project.dot'.execute([], dot.parentFile)
//        p.waitFor()
//        if (p.exitValue() != 0) {
//            throw new RuntimeException(p.errorStream.text)
//        }
//
//        println("Project module dependency graph created at ${dot.absolutePath}.png")
    }
}

引用:

java 复制代码
apply from: "${project.rootProject.file('projectDependencyGraph.gradle')}"

运行脚本 :

shell 复制代码
gradlew projectDependencyGraph

根目录会生成 build\reports\dependency-graph\project.dot

执行完命令后,会生成对应的dot文件

dot 是图形描述语言,简单来说就是用来描述一个图片的

查看

网页打开 .dot在线预览,复制.dot内容进入,即可查看

利用graphviz将dot可视化转为图片

为了把 dot 文件转 png 图片,你的机器上需要安装 GraphvizDownload | Graphviz。这玩意就是把 dot 转 png 的工具。

使用graphviz命令生成图即可,如下:

shell 复制代码
dot .\pp.dot -T jpg -o 11.jpg

若电脑上已安装Graphviz,可把上面脚本注释部分打开,即可把dot文件直接生成图片。

把上面脚本注释部分打开,电脑上未安装Graphviz,会报错 :

java.io.IOException:

Cannot run program "dot" (in directory "\build\reports\dependency-graph"):

CreateProcess error=2, 系统找不到指定的文件。

下载了Graphviz,命令行输入dot -V,若找不到命令需要配置环境变量。我这里是直接在path中添加bin目录即可。

相关推荐
应用市场1 小时前
离线小游戏做“每日挑战”:日期当随机种子,整局存成 JSON,再加一个“我不是机器人”
android·kotlin·游戏开发
一铭111992 小时前
海豹办公 1.9.15 跨端办公软件实践 文档兼容 Access 数据库与移动 WebView 排错
android·数据库·electron·开源软件·access
geats人山人海2 小时前
java 7异常
android·java·开发语言
2601_962071003 小时前
Kimi K3 vs DeepSeek V4-Pro实测对比:2026年同一入口十道题,耗时与token消耗差在哪
android·java·数据库
2501_915918413 小时前
在 Xcode 中运行和调试单元测试的完整指南
ide·vscode·macos·ios·单元测试·个人开发·xcode
右手吉他4 小时前
高通平台IA APN问题分析之二
android·物联网
夜雪一千5 小时前
MySQL 自增 ID 的底层原理与坑点
android·mysql·adb
不浪费一个字节5 小时前
一个纯 Python 实现的 APK 解析与设备操控工具箱
android
itmigrate5 小时前
PHP 导出大 CSV 时内存溢出的一次排查
android·开发语言·php
hai_android5 小时前
LiveEventBusCore 跨 Activity 通讯源码解析
android·kotlin·android jetpack