What's the difference between implementation and compile in Gradle?

前端 未结 9 1484
北荒
北荒 2020-11-22 03:01

After updating to Android Studio 3.0 and creating a new project, I noticed that in build.gradle there is a new way to add new dependencies instead of comp

相关标签:
9条回答
  • 2020-11-22 03:17

    Compile configuration was deprecated and should be replaced by implementation or api.

    You can read the docs at https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation.

    The brief part being-

    The key difference between the standard Java plugin and the Java Library plugin is that the latter introduces the concept of an API exposed to consumers. A library is a Java component meant to be consumed by other components. It's a very common use case in multi-project builds, but also as soon as you have external dependencies.

    The plugin exposes two configurations that can be used to declare dependencies: api and implementation. The api configuration should be used to declare dependencies which are exported by the library API, whereas the implementation configuration should be used to declare dependencies which are internal to the component.

    For further explanation refer to this image.

    0 讨论(0)
  • 2020-11-22 03:25

    Brief Solution:

    The better approach is to replace all compile dependencies with implementation dependencies. And only where you leak a module’s interface, you should use api. That should cause a lot less recompilation.

     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'
             })
     }
    

    Explain More:

    Before Android Gradle plugin 3.0: we had a big problem which is one code change causes all modules to be recompiled. The root cause for this is that Gradle doesn’t know if you leak the interface of a module through another one or not.

    After Android Gradle plugin 3.0: the latest Android Gradle plugin now requires you to explicitly define if you leak a module’s interface. Based on that it can make the right choice on what it should recompile.

    As such the compile dependency has been deprecated and replaced by two new ones:

    • api: you leak the interface of this module through your own interface, meaning exactly the same as the old compile dependency

    • implementation: you only use this module internally and does not leak it through your interface

    So now you can explicitly tell Gradle to recompile a module if the interface of a used module changes or not.

    Courtesy of Jeroen Mols blog

    0 讨论(0)
  • 2020-11-22 03:25

    The brief difference in layman's term is:

    • If you are working on an interface or module that provides support to other modules by exposing the members of the stated dependency you should be using 'api'.
    • If you are making an application or module that is going to implement or use the stated dependency internally, use 'implementation'.
    • 'compile' worked same as 'api', however, if you are only implementing or using any library, 'implementation' will work better and save you resources.

    read the answer by @aldok for a comprehensive example.

    0 讨论(0)
  • 2020-11-22 03:27
    • implementation: mostly we use implementation configuration. It hides the internal dependency of the module to its consumer to avoid accidental use of any transitive dependency, hence faster compilation and less recompilation.

    • api: must be used very carefully, since it leaks the to consumer’s compile classpath, hence misusing of api could lead to dependency pollution.

    • compileOnly: when we don’t need any dependency at runtime, since compileOnly dependency won’t become the part of the final build. we will get a smaller build size.

    • runtimeOnly: when we want to change or swap the behaviour of the library at runtime (in final build).

    I have created a post with an in-depth understanding of each one with Working Example: source code

    https://medium.com/@gauraw.negi/how-gradle-dependency-configurations-work-underhood-e934906752e5

    0 讨论(0)
  • 2020-11-22 03:28

    This answer will demonstrate the difference between implementation, api, and compile on a project.


    Let's say I have a project with three Gradle modules:

    • app (an Android application)
    • myandroidlibrary (an Android library)
    • myjavalibrary (a Java library)

    app has myandroidlibrary as dependencies. myandroidlibrary has myjavalibrary as dependencies.

    myjavalibrary has a MySecret class

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

    myandroidlibrary has MyAndroidComponent class that manipulate value from MySecret class.

    public class MyAndroidComponent {
    
        private static String component = MySecret.getSecret();
    
        public static String getComponent() {
            return "My component: " + component;
        }    
    }
    

    Lastly, app is only interested in the value from myandroidlibrary

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

    Now, let's talk about dependencies...

    app need to consume :myandroidlibrary, so in app build.gradle use implementation.

    (Note: You can use api/compile too. But hold that thought for a moment.)

    dependencies {
        implementation project(':myandroidlibrary')      
    }
    

    What do you think myandroidlibrary build.gradle should look like? Which scope we should use?

    We have three options:

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

    What's the difference between them and what should I be using?

    Compile or Api (option #2 or #3)

    If you're using compile or api. Our Android Application now able to access myandroidcomponent dependency, which is a MySecret class.

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

    Implementation (option #1)

    If you're using implementation configuration, MySecret is not exposed.

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

    So, which configuration you should choose? That really depends on your requirement.

    If you want to expose dependencies use api or compile.

    If you don't want to expose dependencies (hiding your internal module) then use implementation.

    Note:

    This is just a gist of Gradle configurations, refer to Table 49.1. Java Library plugin - configurations used to declare dependencies for more detailed explanation.

    The sample project for this answer is available on https://github.com/aldoKelvianto/ImplementationVsCompile

    0 讨论(0)
  • 2020-11-22 03:28
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | Name               | Role                 | Consumable? | Resolveable? | Description                             |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | api                | Declaring            |      no     |      no      | This is where you should declare        |
    |                    | API                  |             |              | dependencies which are transitively     |
    |                    | dependencies         |             |              | exported to consumers, for compile.     |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | implementation     | Declaring            |      no     |      no      | This is where you should                |
    |                    | implementation       |             |              | declare dependencies which are          |
    |                    | dependencies         |             |              | purely internal and not                 |
    |                    |                      |             |              | meant to be exposed to consumers.       |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | compileOnly        | Declaring compile    |     yes     |      yes     | This is where you should                |
    |                    | only                 |             |              | declare dependencies                    |
    |                    | dependencies         |             |              | which are only required                 |
    |                    |                      |             |              | at compile time, but should             |
    |                    |                      |             |              | not leak into the runtime.              |
    |                    |                      |             |              | This typically includes dependencies    |
    |                    |                      |             |              | which are shaded when found at runtime. |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | runtimeOnly        | Declaring            |      no     |      no      | This is where you should                |
    |                    | runtime              |             |              | declare dependencies which              |
    |                    | dependencies         |             |              | are only required at runtime,           |
    |                    |                      |             |              | and not at compile time.                |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | testImplementation | Test dependencies    |      no     |      no      | This is where you                       |
    |                    |                      |             |              | should declare dependencies             |
    |                    |                      |             |              | which are used to compile tests.        |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | testCompileOnly    | Declaring test       |     yes     |      yes     | This is where you should                |
    |                    | compile only         |             |              | declare dependencies                    |
    |                    | dependencies         |             |              | which are only required                 |
    |                    |                      |             |              | at test compile time,                   |
    |                    |                      |             |              | but should not leak into the runtime.   |
    |                    |                      |             |              | This typically includes dependencies    |
    |                    |                      |             |              | which are shaded when found at runtime. |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    | testRuntimeOnly    | Declaring test       |      no     |      no      | This is where you should                |
    |                    | runtime dependencies |             |              | declare dependencies which              |
    |                    |                      |             |              | are only required at test               |
    |                    |                      |             |              | runtime, and not at test compile time.  |
    +--------------------+----------------------+-------------+--------------+-----------------------------------------+
    
    0 讨论(0)
提交回复
热议问题