In 2019, Google announced that Android development is officially Kotlin-first. Kotlin is a modern, statically typed programming language developed by JetBrains that compiles down to JVM bytecode. It was explicitly designed to eradicate the most notorious pitfalls of Java — chief among them the catastrophic NullPointerException ("The Billion Dollar Mistake").
In Kotlin, the type system strictly distinguishes between references that can hold null and those that cannot:
// Non-nullable variable (can NEVER be null)
var appTitle: String = "Veewom Android"
// appTitle = null // COMPILE ERROR! Won't even build.
// Nullable variable (explicitly marked with ?)
var userEmail: String? = null
userEmail = "student@veewom.com"
// Safe Call Operator (?.)
val emailLength: Int? = userEmail?.length
// Elvis Operator (?:) - Provides a fallback default value
val lengthOrDefault: Int = userEmail?.length ?: 0
// Safe Cast (as?)
val text: String? = someObject as? String
In Java, creating a simple model with getters, setters, equals(), hashCode(), and toString() required 50+ lines of code. In Kotlin, a Data Class accomplishes all of that in a single, expressive line:
data class UserProfile(
val id: Int,
val username: String,
val email: String,
val isVerified: Boolean = false // Default argument value
)
// Automatic copy() with mutation for immutable state updates
val user1 = UserProfile(1, "alex99", "alex@veewom.com")
val updatedUser = user1.copy(isVerified = true)
Modern Android architectures model UI screens using Sealed Interfaces. Because the compiler knows every possible subclass, your when expressions are strictly exhaustive without requiring brittle else branches:
sealed interface ScreenUiState {
object Loading : ScreenUiState
data class Success(val articles: List<String>) : ScreenUiState
data class Error(val message: String) : ScreenUiState
}
// In Jetpack Compose:
@Composable
fun ArticleScreen(state: ScreenUiState) {
when (state) {
is ScreenUiState.Loading -> CircularProgressIndicator()
is ScreenUiState.Success -> ArticleList(state.articles)
is ScreenUiState.Error -> ErrorBanner(state.message)
} // Exhaustive! No 'else' needed.
}
Kotlin permits you to extend existing classes with new functionality without inheriting from them or modifying their source code:
// Extension on standard Android Context class
fun Context.showToast(message: String, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, duration).show()
}
// Extension on String to validate emails
fun String.isValidEmail(): Boolean {
return android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}
// Usage inside an Activity:
showToast("Welcome to Veewom!")
val valid = "test@domain.com".isValidEmail()
Kotlin provides concise scope functions for executing code blocks within the context of an object:
| Function | Context Object | Return Value | Primary Idiomatic Use Case |
|---|---|---|---|
| let | it |
Lambda result | Null checks: user?.let { sendNotification(it) } |
| apply | this |
Context object | Object configuration (e.g., setting up Intent or Paint properties) |
| also | it |
Context object | Side effects, logging, and intermediate debug prints |
| run | this |
Lambda result | Object configuration combined with computing a final result |
Broaden your foundational and advanced Android application development skills across our curriculum:
Deep dive into Kotlin Dispatchers, suspend functions, and Flow streaming.
Leverage Kotlin mutableStateOf, StateFlow, and immutable data classes.
Preserve state across configuration changes using Kotlin Flow.
Practice Kotlin and Android technical interview questions.