mm_857
mm_857

Reputation: 171

Advantage of 'implementation' in build.gradle

Say I have a project, ProjectA, containing ClassInProjectA which I build into an .aar. I also have a project, ProjectB, which uses ClassInProjectA internally.

public class ClassInProjectB {
    public ClassInProjectB() {
        new ClassInProjectA();
    }
}

The build.gradle of ProjectB is as follows:

android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation(name:'projA', ext:'aar')
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

I use implementation because ClassInProjectA is used only internally by ProjectB.

I then have a main app and wish to use ClassInProjectB. The main app's build.gradle is as follows:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.project.projectc"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation(name:'projB', ext:'aar')
    implementation(name:'projA', ext:'aar')

    implementation 'com.android.support:appcompat-v7:28.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

projB needs to be imported explicitly or I am unable to construct ClassInProjectB, due to the requirement for ClassInProjectA.

All is well, all compiles and ClassInProjectB can be constructed.

If the build.gradle of ProjectB is changed such that projA is an api requirement:

api(name:'projA', ext:'aar')

nothing changes in the build.gradle of the main app.

What is the advantage of the implementation keyword in this context? Is it purely that it allows me to replace ProjectB in the main app and avoid triggering a recompilation of Project A?

I'm also a little confused by this post, and this one, each of which imply that the main project shouldn't actually need to implicitly import ProjectA at all if ProjectB depends on ProjectA via the api keyword. Have I misunderstood something? edit: this would seem to be the case only if the dependencies are via submodules in the same project rather than exported .aar.

Upvotes: 1

Views: 1087

Answers (1)

Martijn
Martijn

Reputation: 5611

What is the advantage of the implementation keyword in this context? Is it purely that it allows me to replace ProjectB in the main app and avoid triggering a recompilation of Project A?

The only advantage of the implementation keyword, and indeed the reason why it was introduced, is that it can avoid full project rebuilds. This blogpost does a great job at explaining the details. To summarize, if :projectA has an implementation dependency on :projectB, then :projectA only needs to be recompiled if the interface of :projectB changes.

Upvotes: 1

Related Questions