Gradle 编译的那些坑

说到 Gradle 编译,相信每个 Android 开发者都或多或少曾经被坑过。因为gradle依赖的仓库都在国外,而国内访问国外网络都情况大家也都懂得。我司的情况就更严重了,20 多个内部依赖,50 多个三方依赖。然后光 root gradle 文件里就有这么多仓库(不要问我为什么):

repositories {
       jcenter()
       mavenCentral()
       google()
       maven {
           url "http://127.0.0.1:8081/nexus/content/repositories/releases/"  // 127.0.0.1 代指内部 maven 仓库
       }
       maven {
           url "http://127.0.0.1:8081/nexus/content/repositories/central"
       }
       maven {
           url "http://127.0.0.1:8081/nexus/content/repositories/snapshots"
       }
       maven {
           url "http://127.0.0.1:8081/nexus/content/groups/public"
       }
       maven { url "https://jitpack.io" }
       maven {
           url "https://oss.sonatype.org/content/repositories/snapshots/"
       }
       mavenLocal()
}

每次拉一个新仓库下来,光 sync dependencies 就要好久。万一中间再遇到什么坑,那就有得搞了,有时候一两天都不一定能解决。本篇文章就是笔者总结的遇到的 gradle sync 中遇到的一些坑。

先试试重启大法?

重启试试? Invalidate Caches and Restart 了解一下?

大坑:JCenter 被墙

如果你最近突然发现 jcenter 上的东西一直拉不下来,那大概率是 jcenter 被墙了。
解决方案:
全局替换 jcenter 源到 aliyun mirror:

~/.gradle 目录下新建 init.gardle 文件,输入以下内容:

gradle.projectsLoaded {
    rootProject.allprojects {
        buildscript {
            repositories {
                def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
                all { ArtifactRepository repo ->
                    if (repo instanceof MavenArtifactRepository) {
                        def url = repo.url.toString()
                        if (url.startsWith('https://repo1.maven.org/maven2')
                            || url.startsWith('https://jcenter.bintray.com/')) {
                            project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
                            println("buildscript ${repo.url} replaced by $REPOSITORY_URL.")
                            remove repo
                        }
                    }
                }
                jcenter {
                    url REPOSITORY_URL
                }
            }
        }
        repositories {
            def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
            all { ArtifactRepository repo ->
                if (repo instanceof MavenArtifactRepository) {
                    def url = repo.url.toString()
                    if (url.startsWith('https://repo1.maven.org/maven2')
                        || url.startsWith('https://jcenter.bintray.com/')) {
                        project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
                        println("allprojects ${repo.url} replaced by $REPOSITORY_URL.")
                        remove repo
                    }
                }
            }
            jcenter {
                url REPOSITORY_URL
            }
        }
    }
}

Gradle 缓存存放位置

~/.gradle/caches/modules-2/files-2.1 这个目录下可以找到你依赖的所有 gradle 库的包。

明明有缓存,却提示一直拉不下来?

之前我曾遇到过某两个库依赖一直无法拉下来的问题,遂从别人电脑的 cache 路径下 copy 过来对应目录,以为这样就能解决了。却发现 gradle sync 无论如何也无法重试,挂了代理,切换 offline mode… 都尝试未果。 后来经分析 Gradle 在每个项目的 .gradle 目录下生成了一份 hash 映射,对应每个版本一份。在第一次获取这个依赖库的时候生成,此后就一直根据这个 hash 查找。然而有个很坑爹的问题是,这个 hash 值在没台电脑下都不一致。而 gradle 在下载依赖时,只会根据依赖包命和版本号判断对应依赖是否已经存在在缓存中。所以就出了这个现象:明明缓存里有,但 gradle 编译就是找不到,然后又一直不会去下载。
解决方案:
删除工程目录下的 .gradle 目录和本地 ~/.gradle/caches/modules-2/files-2.1 下的所有文件,然后重启 AS 进行 sync。

    原文作者:TonyLeee
    原文地址: https://www.jianshu.com/p/20a6aba4c8fb
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞