Skip to content

Lambda Expressions

codepath-wiki-review[bot] edited this page May 26, 2026 · 32 revisions

Overview

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();
});

Method References

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"); 
}

RxJava

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:

Setup

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:

Using Java 8+ APIs (optional)

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.

Converting Lambda Expressions with Android Studio

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.

Troubleshooting

  • If lambda expressions fail to compile with a message about Java 8 source not being supported, double-check that the compileOptions block above is set inside the android { ... } block of your module-level build.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.

Attribution

This guide was originally drafted by Adegeye Mayowa.

References

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.

Clone this wiki locally