Android -Gradle依賴匯入及相關知識

weixin_34365417發表於2018-08-20

前言

近期匯入了一個專案,因為種種原因始終是失敗,各種引入錯誤,不是這個就是那個,歸根到底還是對gradle相關知識不夠了解,今天來整理一下。

升級3.x.x變化

Gradle近期變化

android studio版本升級到3.0.0已經有一段時間了,現在使用的是studio 3.1.2.那麼(當然預設你的build:gradle:3.1.2,二者要保持一致)。升級到3.x.x之後版本,有啥變化呢?

  • 支援java8。
  • 支援kotlin,預設安裝相關外掛。
  • gradle編譯速度有所加速。

依賴變化

3.0.0之前 3.0.0之後 說明
compile implementation 將該依賴隱藏在內部,而不對外部公開。比如:app依賴於moudle1,而moudle1 implementation Glide庫,那麼app如果直接引用moudle1,可以使用moudle1中採用implementation依賴的Glide庫嗎?答案是:不可以!(之前是可以的),app需要自己依賴Glide才可以使用.這麼做的好處是雖然使用起來複雜了但是做到降低偶合興提高安全性。
api 完全等同於compile指令沒區別
provided compileOnly 只在編譯時有效,不會參與打包 ,可以避免包衝突
apk runtimeOnly 只在生成apk的時候參與打包,編譯時不會參與
testCompile testImplementation testCompile 只在單元測試程式碼的編譯以及最終打包測試apk時有效
debugCompile debugImplementation debugCompile 只在debug模式的編譯和最終的debug apk打包時有效
releaseCompile releaseImplementation Release compile 僅僅針對Release 模式的編譯和最終的Release apk打包

Project build.gradle

6748497-3bed6a2bc49a78a7.png
Project build.gradle

我們們一個一個解釋其含義:

  • buildscript:用來載入gradle指令碼自身需要使用的資源,可以宣告的資源包括依賴項、第三方外掛、maven倉庫地址等
  • repositories表示程式碼倉庫的下載來源
  • jcente 是一個新的中央遠端倉庫,相容maven中心倉庫,而且效能更優.
  • google 是google的程式碼託管倉庫
  • dependencies一般是執行Gradle需要的gradle工具。
  • classpath 執行gradle需要的工具地址,一般版本號同studio版本保持一致
  • allproject 是整個專案的配置,比如allproject 中的repositories和上面buildscript的區別就是:前者allproject是整個專案本身需要的依賴,後者是gradle指令碼執行所需依賴(Gradle外掛),分別是對應的maven倉庫和外掛依賴等
  • task clear 執行gradle clean時,執行此處定義的task. 該任務繼承自Delete,刪除根目錄中的build目錄。

常見的遠端依賴方式

方式一

implementation 'com.android.support.constraint:constraint-layout:1.1.2'

方式二

implementation group: 'com.android.support.constraint', name: 'constraint-layout', version: '1.1.2'

方式三
   implementation('com.android.support.constraint:constraint-layout:1.1.2') {
        //不同版本同時被依賴時,那麼強制依賴這個版本的,預設false
        force = true
        //exclude可以設定不編譯指定的模組,有三種寫法:
    exclude module: 'abc'
    exclude group: 'bcd'
    exclude group: 'abc', module: 'bcd'
        //禁止依賴的傳遞,gradle自動新增子依賴項,預設為true.
        transitive = true
    }

當然我們這裡的exclude 的‘abc’等內容是不存在的,只是給大家演示,由此也引出了exclude的一個作用,避免依賴包衝突。那麼除了採用exclude這種方式,我們還有沒有別的方法呢,答案當然是有了,那就是統一為所有依賴指定依賴包的版本,如下:

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '28.0.0-rc01'
            }
        }
    }
}

在 project 的 build.gradle 中新增如下的程式碼,該程式碼的意思是:在專案構建時,遍歷所有依賴,然後 com.android.support 包下的依賴替換同一個版本。但此方法也有弊端:就是每次構建的時候,多了一個遍歷過程,會加長構建時間。因此,推薦使用 exclude 關鍵字排除。

那我們如何判斷是那幾個library的檔案衝突了呢?

首先studio會先報出該錯誤,在log日誌中會有某個moudle的資訊。然後我們需要一個命令:

./gradlew -q <模組名>:dependencies
如:gradlew -q app:dependencies 檢視app這個module的依賴其他庫的資訊,看看有沒有衝突
該命令能列印出該模組所有的依賴樹資訊,然後我們根據具體log資訊,採用exclud方式解決問題。

本地依賴

Jar包依賴
6748497-debc2a8631ef2b46.png
image
arr檔案的依賴
  • 首先先宣告aar包存放的路徑宣告
 repositories {
        flatDir {
            dirs 'libs' //此處宣告存放路徑為lib資料夾下
        }
    }
  • 其次依賴引入
    implementation(name: 'LibReplayDecode-release', ext: 'aar')

so檔案的依賴

宣告下so檔案的存放路徑即可

  sourceSets {
      main {
          //配置so載入目錄
          jniLibs.srcDirs = ['libs']

      }
  }

當然也可以在main目錄下新建jniLibs目錄,這是so檔案預設的放置目錄,不過本人一般不習慣這樣,還有需要注意:並不是將so檔案直接放入lib資料夾下,而是需要建立對應的ABI目錄下(Android 裝置的CPU型別通常稱為”ABIs”),也就是說不同的armeabi檔案是為了專門針對不同Android手機下CPU架構的相容,存放so庫。如圖:

6748497-f0703df2cc4d3ccf.png
image

其他

用過butterknife的同志一定對annotationProcessor不陌生吧,它是一個編譯期註解的依賴。這種方式是隻在編譯的時候執行依賴的庫,但是庫最終不打包到apk中。結合編譯期註解的作用,他是用來生成程式碼的,本身在執行時是不需要的,那麼它與我們上面說的與compileOnly的區別是什麼呢?
annotationProcessor作用是編譯時生成程式碼,編譯完真的就不需要了,compileOnly是有重複的庫,為的是剃除只保留一個庫,最終還是需要的。

相關文章