2017-06-12 57 views
346

編譯更新到Android Studio的3.0和創建新項目後,我注意到,在build.gradle有加,而不是compile新的依賴有和implementation代替testCompile有一種新的方式testImplementation什麼是執行之間的差異和gradle這個

比如:

implementation 'com.android.support:appcompat-v7:25.0.0' 
testImplementation 'junit:junit:4.12' 

代替

compile 'com.android.support:appcompat-v7:25.0.0' 
testCompile 'junit:junit:4.12' 

什麼是它們之間的區別,什麼我應該使用?

回答

496

它是與gradle這個即將到來的重大更改之一:3.0,谷歌announced at IO17 gradle產出:3.0

compile配置爲now deprecated,應由implementationapi

gradle docs替代:

dependencies { 
    api 'commons-httpclient:commons-httpclient:3.1' 
    implementation 'org.apache.commons:commons-lang3:3.5' 
} 

出現在api中的相關性配置將 傳遞地暴露給消費者的庫,並因此將出現 對消費者的編譯類路徑。

implementation配置中發現的依賴關係將在 另一方面,不會泄露給消費者,因此不會泄漏到消費者的編譯類路徑中 。這提供了幾個好處:

  • 依賴性不泄漏到消費者的編譯類路徑中了,所以你永遠不會意外地取決於傳遞 依賴
  • 更快的編譯由於減少了classpath中尺寸
  • 更少的重新編譯當執行依賴性改變:消費者不會需要重新編譯
  • 清潔出版:結合新的Maven的發佈插件時,Java庫產生 區分之間究竟需要什麼COM POM文件樁針對 庫,什麼是需要使用運行時庫(在其他 的話,不要混用,什麼是需要編譯庫本身以及需要什麼 進行編譯庫)。

編譯配置仍然存在,但不應該使用,因爲它不會提供api和實現配置提供的保證。


TL;博士

只需更換:

  • compileimplementation
  • testCompiletestImplementation
  • debugCompiledebugImplementation
  • androidTestCompileandroidTestImplementation
+50

誰是「消費者」? – Suragch

+11

消費者是使用庫的模塊。在Android的情況下,它是Android應用程序。我認爲這很清楚,我不確定這是否是你要求的。 – humazed

+9

這也是我聽起來的樣子。但是,如果我正在創建一個庫,當然我希望它的API能夠暴露給應用程序。否則,應用程序開發人員將如何使用我的庫?這就是爲什麼我沒有獲得隱藏依賴項的「實現」的含義。我的問題有意義嗎? – Suragch

33

Compile配置已被廢棄,應由implementationapi代替。

您可以閱讀https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation的文檔。

簡要部分即─

標準Java插件和Java 庫插件之間的主要區別是,後者引入了暴露給消費者的API 的概念。一個庫是一個Java組件,它被其他組件所使用,意圖是 。這是 多項目構建中的一個非常常見的用例,但是也會在您有外部 依賴項時立即生效。

該插件公開了兩種配置,可用於聲明 依賴項:api和實現。 api配置應該是 ,用於聲明由庫API導出的依賴關係, ,而實現配置應用於聲明組件內部的依賴關係。

欲瞭解更多信息,請參考此圖片。 Brief explanation

18

簡要方案:

更好的方法是implementation依賴全部更換compile依賴。只有當你泄漏模塊的接口時,你應該使用api。這應該會導致很少的重新編譯。

dependencies { 
     implementation fileTree(dir: 'libs', include: ['*.jar']) 

     implementation 'com.android.support:appcompat-v7:25.4.0' 
     implementation 'com.android.support.constraint:constraint-layout:1.0.2' 
     // … 

     testImplementation 'junit:junit:4.12' 
     androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { 
      exclude group: 'com.android.support', module: 'support-annotations' 
     }) 
} 

更多地解釋:

Android的搖籃插件3.0前:我們有一個很大的問題,就是一個代碼變化導致重新編譯所有模塊。造成這種情況的根本原因是Gradle不知道是否通過另一個模塊泄漏了模塊的接口。

Android Gradle插件後3。0:最新的Android Gradle插件現在要求您明確定義是否泄漏模塊的接口。基於此,它可以對應該重新編譯的內容做出正確的選擇。

這樣的compile依賴已被棄用,由兩個新的取代:

  • api:您泄漏該模塊的接口,通過自己的界面,這意味着完全一樣老compile依賴

  • implementation:你只在內部使用這個模塊,並通過你的接口不泄漏

所以現在你可以明確地告訴Gradle重新編譯一個模塊,如果所使用的模塊的接口改變或者不改變的話。

Jeroen Mols博客的禮貌

26

這個答案將展示在一個項目implementationapicompile之間的差異。比方說,我有三個搖籃模塊項目:

  • 應用(Android應用程序)
  • myandroidlibrary(一個Android庫)
  • myjavalibrary(一個Java庫)

appmyandroidlibrary作爲依賴關係。 myandroidlibrary具有myjavalibrary作爲依賴關係。

應用 - > myandroidlibrary - > myjavalibrary

myjavalibrary具有MySecret

public class MySecret { 

    public static String getSecret() { 
     return "Money"; 
    } 
} 

myandroidlibrary具有MyAndroidComponent類,從類MySecret操縱值。

public class MyAndroidComponent { 

    private static String component = MySecret.getSecret(); 

    public static String getComponent() { 
     return "My component: " + component; 
    }  
} 

最後,app僅在值從myandroidlibrary

TextView tvHelloWorld = findViewById(R.id.tv_hello_world); 
tvHelloWorld.setText(MyAndroidComponent.getComponent()); 

現在感興趣的,讓我們來談談依賴於app的build.gradle。它非常簡單直觀。

dependencies { 
    implementation project(':myandroidlibrary')  
} 

你覺得myandroidlibrary的build.gradle應該樣子?我們有三個選擇:

dependencies { 
    // Option #1 
    implementation project(':myjavalibrary') 
    // Option #2 
    compile project(':myjavalibrary')  
    // Option #3 
    api project(':myjavalibrary')   
} 

什麼是它們之間的區別,什麼我應該使用?

編譯和API

如果您使用compileapi。我們的Android應用程序現在能夠訪問myandroidcomponent依賴項,這是一個MySecret類。

TextView textView = findViewById(R.id.text_view); 
textView.setText(MyAndroidComponent.getComponent()); 
// You can access MySecret 
textView.setText(MySecret.getSecret()); 

實施

如果您使用implementation配置,MySecret不外露。

TextView textView = findViewById(R.id.text_view); 
textView.setText(MyAndroidComponent.getComponent()); 
// You can NOT access MySecret 
textView.setText(MySecret.getSecret()); // Won't even compile 

那麼,您應該選擇哪種配置?這真的取決於你的要求。

如果你想揭露依賴使用apicompile,如果你不希望暴露依賴(隱藏你的內部模塊),然後使用implementation

這只是Gradle配置的一個要點,Table 49.1. Java Library plugin - configurations used to declare dependencies對此有更詳細的解釋。

快樂探索

相關問題