-
Notifications
You must be signed in to change notification settings - Fork 6.2k
Lambda Expressions
Java 8 lambda expressions help eliminate boilerplate code that makes the syntax verbose and less clear. For instance, consider the standard basic click listener:
myButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("debug", "Button clicked");
}
});Lambda expressions can greatly simplify this code, especially in this case where the event listener has only one method that needs to be implemented:
myButton.setOnClickListener(v -> Log.d("debug", "Button clicked"));If you have more than one line to execute, then you should surround the block of code with braces:
myButton.setOnClickListener(v -> {
Log.d("debug", "Button clicked");
Toast.makeText(MyActivity.this, "here", Toast.LENGTH_LONG).show();
});You may also notice in some cases lambda expressions also contain double colons ::. These refer to a new syntax in Java 8 known as method references. You can reference a class or instance and pass along the method that will handle the event:
public void onCreate() {
myButton.setOnClickListener(this::logError);
}
public void logError(View v) {
Log.d("debug", "Button clicked");
}Lambda expressions are especially helpful in RxJava as well. Take a look at the code below for creating an Observable and subscribing an Observer to it.
Creating and subscribing to an observable without lambdas:
Observable.just("1", "2", "3")
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
Log.d("debug", "complete");
}
@Override
public void onError(Throwable throwable) {
Log.d("debug", throwable.getMessage());
}
@Override
public void onNext(String s) {
Log.d("debug", s);
}
});Consider the same code with lambda expressions:
Observable.just("1", "2", "3")
.subscribe(
value -> Log.d("debug", value),
throwable -> Log.d("debug", throwable.getMessage()),
() -> Log.d("debug", "complete"));Lambda expressions rely on type inference to fill in the blanks. Notice that the right-hand side of the arrow does not require a return statement if you do not surround the block with { and }. Also notice that a function with zero or multiple arguments need parenthesis enclosing them.
You can look to the left of Android Studio to see how it is inferring which type to use:
Lambda expressions, method references, and the rest of the Java 8 language features are supported out of the box by the Android Gradle Plugin (AGP) 3.0 or higher — no external plugin (such as the old Retrolambda) and no opt-in toolchain (such as the deprecated Jack) is required. AGP relies on a bytecode-level desugar step to make the features run on every supported minSdk.
To enable Java 8 source on a module, set sourceCompatibility and targetCompatibility in the module-level build.gradle (Groovy DSL):
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// For Kotlin projects, also set the JVM target.
kotlinOptions {
jvmTarget = "1.8"
}
}Or, in build.gradle.kts (Kotlin DSL) — note the = assignment operator:
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}That is the entire setup — there is no separate apply plugin: 'me.tatarka.retrolambda', no jackOptions { enabled true }, and no need to add a custom buildscript classpath. Newly created projects from Android Studio already include this block.
Heads up about the old approaches. If you are reading older tutorials or maintaining an app that still references them:
- The Jack toolchain was officially deprecated by Google in March 2017 and removed from later AGP releases. Remove any
jackOptionsblock from yourbuild.gradle.- The third-party Gradle Retrolambda plugin has been explicitly deprecated by its maintainer in favor of AGP's built-in support. Remove
apply plugin: 'me.tatarka.retrolambda'and the matchingclasspathdependency.
If you also want to use Java 8+ standard library APIs such as java.time, java.util.stream, or java.util.Optional across all supported minSdk levels, enable core library desugaring (requires AGP 4.0+):
// build.gradle (Groovy DSL)
android {
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
}Or for build.gradle.kts (Kotlin DSL):
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
}See Java 8+ API desugaring support for the full feature list and the latest desugar_jdk_libs version.
If you wish to convert your code to lambda expressions, move your cursor to the slightly greyed out section of your anonymous class and look on the left-hand side of the Android Studio editor for the light bulb:
Once you see the Replace with lambda appear, you can also apply Fix all click on the left-hand side to convert all the possible candidates automatically as outlined here.
- If lambda expressions fail to compile with a message about Java 8 source not being supported, double-check that the
compileOptionsblock above is set inside theandroid { ... }block of your module-levelbuild.gradle, not the root project file. - Make sure the JDK configured in Android Studio (Settings → Build, Execution, Deployment → Build Tools → Gradle) is JDK 8 or newer — recent versions of Android Studio ship with an embedded JDK that satisfies this automatically.
This guide was originally drafted by Adegeye Mayowa.
Created by CodePath with much help from the community. Contributed content licensed under cc-wiki with attribution required. You are free to remix and reuse, as long as you attribute and use a similar license.
Finding these guides helpful?
We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.
Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.