.png)
.png)
Kotlin 2.1 introduces guard conditions in when statements, a feature that allows combining condition matching and boolean checks in a concise and readable way.
Before Kotlin 2.1 introduced guard conditions in when statements, developers had to rely on nested if statements or multiple branches to achieve the same functionality. 
For Android developers, this feature simplifies handling complex scenarios like API responses, user inputs, and dynamic UI behavior.
In this blog, we’ll explore:
- How to enable this feature. 
- Using guard conditions with - when.
- Practical examples, including - else ifbranches.
- Tips for clean, maintainable code. 
What Are Guard Conditions in when Statements?
A guard condition is an additional if clause in a when branch that allows you to add boolean checks for a matched condition. This reduces nested if statements and makes your code more expressive.
Syntax
when (val subject = expression) {
    condition if guardExpression -> { /* action */ }
    else if anotherCondition -> { /* alternate action */ }
    else -> { /* fallback action */ }
}Let’s compare how code looks in older Kotlin versions versus the new Kotlin 2.1 feature, and why this enhancement is so useful.
How when Worked in Older Kotlin Versions
In previous versions of Kotlin (before 2.1), handling additional boolean checks with when required writing nested if statements or duplicating logic for different cases. Here’s an example:
Old Kotlin Implementation
fun validateCredentialsOld(username: String, password: String): String {
    return when (username) {
        "admin" -> {
            if (password.isEmpty()) {
                "Password cannot be empty for admin."
            } else if (password == "admin123") {
                "Welcome, Admin!"
            } else {
                "Invalid admin password."
            }
        }
        else -> {
            if (username.isEmpty()) {
                "Username cannot be empty."
            } else if (password.isEmpty()) {
                "Password cannot be empty."
            } else {
                "Invalid credentials. Please try again."
            }
        }
    }
}In the old approach:
- We needed nested - ifstatements inside- whenbranches to handle additional conditions.
- Logic became harder to follow and less readable, especially as complexity increased. 
- Repeated checks (e.g., - password.isEmpty()) led to code duplication.
How the New Feature Simplifies This
With Kotlin 2.1’s guard conditions, additional checks can now be written inline within when branches using the if keyword. This avoids nesting, reduces duplication, and improves readability.
New Kotlin Implementation (with Guard Conditions)
fun validateCredentials(username: String, password: String): String {
    return when (username) {
        "admin" if password.isEmpty() -> "Password cannot be empty for admin."
        "admin" if password == "admin123" -> "Welcome, Admin!"
        else if username.isEmpty() -> "Username cannot be empty."
        else if password.isEmpty() -> "Password cannot be empty."
        else -> "Invalid credentials. Please try again."
    }
}Advantages of the New Feature:
- No nesting: Guard conditions make additional checks concise and inline. 
- Improved readability: Each branch is self-contained, making the logic easier to understand. 
- Reduced duplication: Avoid repeating logic in multiple branches. 
How to Implement Guard Conditions in Old Kotlin Versions
If you're working in a version of Kotlin that doesn’t support guard conditions, you can replicate similar behavior by:
- Using - ifblocks inside- whenbranches.
- Refactoring into helper functions to reduce nested logic. 
Example: Replicating Guard Conditions in Older Versions
Here’s how you can simulate guard conditions in Kotlin versions before 2.1:
fun validateCredentialsOld(username: String, password: String): String {
    return when {
        username == "admin" && password.isEmpty() -> "Password cannot be empty for admin."
        username == "admin" && password == "admin123" -> "Welcome, Admin!"
        username.isEmpty() -> "Username cannot be empty."
        password.isEmpty() -> "Password cannot be empty."
        else -> "Invalid credentials. Please try again."
    }
}In this example:
- whenuses compound conditions (- &&) to handle cases.
- The nested - ifstatements are removed by moving the logic directly into the condition checks.
Use Cases in Android Development
1. Validating User Input with else if
Consider a login form where you validate the username and password with nuanced error handling:
fun validateCredentials(username: String, password: String): String {
    return when (username) {
        "admin" if password.isEmpty() -> "Password cannot be empty for admin."
        "admin" if password == "admin123" -> "Welcome, Admin!"
        else if username.isEmpty() -> "Username cannot be empty."
        else if password.isEmpty() -> "Password cannot be empty."
        else -> "Invalid credentials. Please try again."
    }
}Key Points:
- The - else ifbranches allow catching additional cases like empty usernames or passwords.
- The - elsebranch acts as a fallback for unmatched cases.
2. Processing API Responses with else if
When handling API responses, you often need to process both success and error cases. Guard conditions with else if simplify this.
fun handleApiResponse(statusCode: Int, errorMessage: String?): String {
    return when (statusCode) {
        200 if errorMessage == null -> "Success! Data loaded."
        400 if errorMessage != null -> "Client Error: $errorMessage"
        500 -> "Server Error: Try again later."
        else if statusCode in 401..499 -> "Authentication Error: Code $statusCode"
        else -> "Unknown Response."
    }
}Key Points:
- The - else ifhandles a range of status codes (401–499) as authentication errors.
- Additional error handling logic stays clean and focused. 
3. Customizing Themes Based on User Preferences
Dynamic themes are common in Android apps. Use guard conditions to handle multiple parameters like orientation and user preferences.
fun getThemeColor(orientation: Int, isDarkMode: Boolean, isHighContrast: Boolean): Int {
    return when (orientation) {
        Configuration.ORIENTATION_PORTRAIT if isDarkMode -> Color.BLACK
        Configuration.ORIENTATION_PORTRAIT if isHighContrast -> Color.YELLOW
        Configuration.ORIENTATION_LANDSCAPE if isDarkMode -> Color.DARK_GRAY
        else if isHighContrast -> Color.ORANGE
        else -> Color.WHITE
    }
}Key Points:
- Guard conditions ( - if isDarkMode,- if isHighContrast) make conditions specific and easier to read.
- The - else ifbranch ensures fallback customization for high contrast mode.
Using Guard Conditions in Jetpack Compose
Jetpack Compose simplifies UI updates, and guard conditions make declarative logic easier. Here’s an example with else if for dynamic styling:
@Composable
fun UserRoleDisplay(role: String, isVerified: Boolean, isPremium: Boolean) {
    val textStyle = when (role) {
        "Admin" if isVerified -> TextStyle(color = Color.Red, fontWeight = FontWeight.Bold)
        "User" if isVerified -> TextStyle(color = Color.Green, fontWeight = FontWeight.Normal)
        "Guest" -> TextStyle(color = Color.Gray, fontStyle = FontStyle.Italic)
        else if isPremium -> TextStyle(color = Color.Gold, fontWeight = FontWeight.Medium)
        else -> TextStyle(color = Color.Black)
    }
    Text(
        text = "Role: $role",
        style = textStyle
    )
}Key Points:
- Guard conditions ( - if isVerified,- if isPremium) determine the user’s style dynamically.
- The - else ifbranch ensures premium users have a unique style even if they’re not explicitly matched by the- whenconditions.
Best Practices for Guard Conditions
- Enable Fallbacks: Always include an - elsebranch to handle unexpected cases.
- Use - else ifWisely: Avoid chaining too many- else ifbranches, as it may reduce readability. Use helper functions for complex conditions.
- Keep It Readable: Use guard conditions only when they improve clarity. Overcomplicating a single branch can lead to hard-to-read code. 
Enabling Guard Conditions in Kotlin
The guard conditions feature is currently experimental in Kotlin 2.1. To use it, you need to enable it in your project.
1. Using the Command Line
If you're running Kotlin files from the command line, use the following command:
kotlinc -Xwhen-guards main.kt2. Configuring in Gradle
For Gradle-based projects (typical in Android development), enable it in your build.gradle.kts:
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xwhen-guards")
    }
}Conclusion
Guard conditions in when statements are a fantastic addition in Kotlin 2.1, enabling more expressive and readable code. For Android developers, this feature is particularly valuable in scenarios like:
- Validating user input. 
- Handling API responses. 
- Customizing UI themes and styles. 
By enabling this feature and using it wisely, you can streamline logic handling in your Kotlin projects. Experiment with when guards and elevate your Android development experience!
Akshay Nandwana
Founder AndroidEngineers
You can connect with me on:
Book 1:1 Session here Click Here
Join our upcoming classes
https://www.androidengineers.in/courses
Get the latest Android development articles delivered to your inbox.