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