如何理清楚 Android 工程的依賴關係?

前言

在 Medium 上看到一篇文章:How to display your Android project dependency graph in your README filejava

講的是如何在你的 GitHub README 文件裏面展現 Android 項目的依賴關係圖。node

它其實就是寫了一個 Gradle Task 腳本,源文件以下:projectDependencyGraph.gradleandroid

代碼:git

// From https://github.com/JakeWharton/SdkSearch/blob/master/gradle/projectDependencyGraph.gradle
// The only difference here is the output directory.

task projectDependencyGraph {
  doLast {
    def dot = new File(rootProject.rootDir, 'gradle/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")
  }
}
複製代碼

腳本內容就是用 dot 生成一個 .dot 文件,這個 dot 是啥呢?github

dot 是圖形描述語言,簡單來講就是用來描述一個圖片的,詳細見維基百科上的說明:DOT(graph description languang)markdown

不過該腳本里面涉及到了把 dot 文件轉 png 的操做,因此你的機器上須要安裝 Graphviz。這玩意就是把 dot 轉 png 的工具,爲了方便你還須要安裝一個 State Art(Android Studio Plugin 裏面能夠直接搜到),而後你就能夠直接運行這個 task 了:app

./gradlew projectDependencyGraph
複製代碼

而後就會生成一個相似下面的圖片:工具

不過呢,該文章還提到就是用 GitHub 的 Action 自動去生成這個圖片,感興趣的小夥伴能夠去康康原文撒~oop

總結一下

其實知道有這個玩意就行,好比 dot ,到須要的時候再去好好看~gradle

相關文章
相關標籤/搜索