On this page
- 1. val, var and type inference
- 2. Functions, default and named arguments
- 3. String templates
- 4. if and when are expressions
- 5. Classes, properties and objects
- 6. Null safety in one minute
- 7. Collections and lambdas
- 8. Lambdas and trailing lambda syntax
- 9. Scope functions: let, apply, also, run, with
- 10. Putting it together: a realistic Android snippet
- Common mistakes
- Frequently asked questions
- Conclusion
Kotlin is a big language, with coroutines, generics, DSLs, multiplatform and more. Beginners often try to learn it all at once. You'll be far more productive if you first master the small core you'll use in every Android file, then pick up the advanced features as you need them.
Every example below is runnable in the Kotlin Playground or shows a real Android pattern.
1. val, var and type inference
val appName = "NotiVault" // read-only reference (prefer this)
var unreadCount = 0 // mutable: use only when the value must change
unreadCount += 1
val price: Double = 499.0 // explicit type when it improves clarity
val tags = listOf("kotlin", "android") // inferred as List<String>Default to val. Immutable values make code, and especially UI state, easier to reason about.
2. Functions, default and named arguments
fun formatPrice(amount: Double, currency: String = "โน", decimals: Int = 2): String =
"$currency${"%.${decimals}f".format(amount)}"
formatPrice(1299.5) // โน1299.50
formatPrice(19.99, currency = "$") // named argument: clear at the call siteDefault arguments remove the need for overloads, and named arguments make calls self-documenting. Compose relies on both heavily, for example Text(text = "Hi", maxLines = 1).
3. String templates
val name = "Kamal"
val items = 3
println("Hi $name, you have $items items") // simple values
println("Total: ${items * 199} (${if (items > 1) "items" else "item"})") // expressions4. if and when are expressions
val label = when (statusCode) {
200 -> "OK"
401, 403 -> "Please sign in again"
in 500..599 -> "Server problem, try later"
else -> "Unexpected error ($statusCode)"
}
val badge = if (unreadCount > 99) "99+" else unreadCount.toString()5. Classes, properties and objects
class Counter(private val max: Int) { // primary constructor + property
var value = 0
private set // readable outside, writable only inside
fun increment() { if (value < max) value++ }
}
data class User(val id: String, val name: String) // equals/hashCode/toString/copy for free
object Analytics { // a singleton
fun log(event: String) = println("event: $event")
}Data classes, sealed classes and enums each get their own article: Data, Sealed and Enum Classes.
6. Null safety in one minute
var nickname: String? = null // the ? means "may be null"
val length = nickname?.length ?: 0 // safe call + Elvis default
nickname?.let { println("Hello, $it") } // run only when not nullFull details are in Kotlin Null Safety Explained.
7. Collections and lambdas
data class Order(val id: Int, val total: Double, val paid: Boolean)
val orders = listOf(Order(1, 250.0, true), Order(2, 999.0, false), Order(3, 120.0, true))
val paidTotal = orders.filter { it.paid }.sumOf { it.total } // 370.0
val ids = orders.map { it.id } // [1, 2, 3]
val biggest = orders.maxByOrNull { it.total } // Order(2, โฆ)
val byStatus = orders.groupBy { if (it.paid) "Paid" else "Pending" }it is the implicit name of a single lambda parameter. More in Collections and Functional Programming.
8. Lambdas and trailing lambda syntax
If a function's last parameter is a function, you can pass the lambda outside the parentheses. This is why Compose code looks like a tree:
Button(onClick = { viewModel.save() }) { // the content lambda trails the call
Text("Save")
}
Column { // only a lambda: no parentheses needed
Text("Title")
Text("Subtitle")
}9. Scope functions: let, apply, also, run, with
| Function | Object reference | Returns | Typical Android use |
|---|---|---|---|
let | it | Lambda result | Run code only for non-null values |
apply | this | The object | Configure an object (Intent, Bundle, Paint) |
also | it | The object | Side effects such as logging |
run | this | Lambda result | Compute a value from an object's members |
with | this | Lambda result | Call several members of one object |
val intent = Intent(context, DetailActivity::class.java).apply {
putExtra("articleId", article.id)
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
savedInstanceState?.getString("query")?.let { restoredQuery -> viewModel.onQueryChange(restoredQuery) }Chains like a?.let { b?.apply { also { โฆ } } } hurt readability. A plain if is often clearer.
10. Putting it together: a realistic Android snippet
data class ArticleUi(val id: String, val title: String, val isNew: Boolean)
class ArticlesViewModel(private val repo: ArticleRepository) : ViewModel() {
private val _items = MutableStateFlow<List<ArticleUi>>(emptyList())
val items: StateFlow<List<ArticleUi>> = _items.asStateFlow()
fun load(now: Long = System.currentTimeMillis()) = viewModelScope.launch {
val dayMillis = 24 * 60 * 60 * 1000L
_items.value = repo.getArticles()
.sortedByDescending { it.publishedAt }
.map { ArticleUi(it.id, it.title.trim(), isNew = now - it.publishedAt < dayMillis) }
}
}Data classes, val, collection operations, lambdas, named arguments and an expression-bodied function all appear in ten lines. This is everyday Android Kotlin.
Common mistakes
- Using
vareverywhere, out of Java habit. - Writing Java-style getters and setters instead of properties.
- Using
==versus===incorrectly:==is structural equality (likeequals);===compares references. - Forgetting that
listOfreturns a read-only list. UsemutableListOfor, better, create a new list.
Frequently asked questions
How long does it take to learn Kotlin basics?
With prior programming experience, a week or two of focused practice. As a first language, plan three to four weeks before moving to Android.
Do I need to learn coroutines as part of the basics?
Learn them right after the basics, once you start Android. They have their own guide: Coroutines and Flow Explained.
Where can I practise?
The Kotlin Playground, Kotlin Koans and small console exercises, then real Android screens.
Conclusion
The Kotlin you'll use daily on Android is a compact set: val and var, functions with defaults, templates, when expressions, classes and data classes, null safety, collections, lambdas and a few scope functions. Master these and Android code becomes much easier to read and write.
Next step: go deeper on the feature that prevents the most crashes, Kotlin Null Safety.
Official references
๐ฑ Apps built by Yunok Tech
Real Android apps on Google Play, free to download.
Walzi4K wallpapers for lock and home screenGet it โธ
NotiVaultNotification history: recover dismissed notificationsGet it โธ
Ready to build real Android applications?
Kotlin fluency makes everything else in Android easier, from coroutines and Flow to Compose and clean architecture. The fastest way to build that fluency is to write real Kotlin every day and get feedback on it.
Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.
Explore the Android course and take your next step as an Android developer.