Question
While developing for Android, I sometimes see Kotlin code like this:
var someModel: SomeViewModel by notNullAndObservable { vm ->
// ...
}
I do not understand what the by keyword means here or what role it plays in this property declaration. How does by work in Kotlin, and what is it doing in examples like this?
Short Answer
By the end of this page, you will understand how Kotlin uses the by keyword for property delegation, why it appears in Android and Kotlin codebases, and how it changes the way a property stores or computes its value. You will also see how delegated properties differ from normal properties, how they work step by step, and when developers use them in real projects.
Concept
In Kotlin, the by keyword often means delegation.
In your example:
var someModel: SomeViewModel by notNullAndObservable { vm ->
// ...
}
someModel is not managing its value entirely by itself. Instead, Kotlin delegates the work of getting and setting the property to another object returned by notNullAndObservable(...).
What is a delegated property?
A delegated property is a property whose behavior is handled by a delegate object.
Instead of writing your own custom getter and setter like this:
var someModel: SomeViewModel = ...
get() = field
set(value) {
field = value
// extra logic
}
You can write:
var someModel: SomeViewModel by someDelegate
Kotlin then translates property access behind the scenes so that:
- reading
someModelcalls the delegate'sgetValue(...) - writing calls the delegate's
Mental Model
Think of a normal property as a box that stores its own value.
A delegated property is more like a front desk clerk.
When you try to read or write the property, you are not opening the box directly. You are asking the clerk to handle the request.
property = value→ the clerk decides how to store itprintln(property)→ the clerk decides how to return it- extra rules can happen in between, like logging, validation, or refusing access before setup
So by is Kotlin's way of saying:
"This property is handled by someone else."
That "someone else" is the delegate object.
Syntax and Examples
Basic delegated property syntax
var name: String by delegateObject
For a read-only property:
val name: String by delegateObject
The delegate object must provide operator functions such as:
operator fun getValue(thisRef: Any?, property: KProperty<*>): String
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String)
val only needs getValue. var needs both getValue and setValue.
Example 1: Using Kotlin's built-in lazy
message: String lazy {
println()
}
{
println(message)
println(message)
}
Step by Step Execution
Consider this example:
import kotlin.properties.Delegates
var status: String by Delegates.observable("offline") { _, oldValue, newValue ->
println("Status changed from $oldValue to $newValue")
}
fun main() {
println(status)
status = "online"
println(status)
}
Step-by-step
1. Property declaration
var status: String by Delegates.observable("offline") { ... }
Kotlin creates a delegate object using Delegates.observable(...).
That delegate stores the current value, starting with "offline".
2. First read
println(status)
This does not read a normal backing field directly.
Instead, Kotlin calls the delegate's getValue(...) function.
The delegate returns "offline".
Real World Use Cases
Delegated properties are used in many practical Kotlin situations.
1. Lazy initialization
val config by lazy { loadConfigFromDisk() }
Use this when an object is expensive to create and should only be built if needed.
2. Observing state changes
var score by Delegates.observable(0) { _, old, new ->
println("Score changed: $old -> $new")
}
Useful for UI state, settings, or debugging value changes.
3. Preventing use before initialization
import kotlin.properties.Delegates
var service: String by Delegates.notNull()
Useful when a property cannot be assigned in the constructor but must be set before use.
4. Validation before accepting a value
import kotlin.properties.Delegates
var age: Int by Delegates.vetoable(0) { _, _, newValue ->
newValue >= 0
}
The delegate can reject invalid updates.
Real Codebase Usage
In real projects, developers use delegated properties to reduce boilerplate and centralize repeated logic.
Common patterns
Guarding access until initialization
A service or view model may not be available immediately:
import kotlin.properties.Delegates
class Controller {
var repository: String by Delegates.notNull()
}
This avoids nullable types when the value should definitely exist before real use.
Reacting to changes automatically
import kotlin.properties.Delegates
class Settings {
var theme: String by Delegates.observable("light") { _, old, new ->
if (old != new) println("Theme updated")
}
}
This is common for syncing state, updating UI, logging, or triggering side effects.
Encapsulating repeated property rules
Teams often create custom delegates to avoid repeating getter/setter logic.
For example, a custom delegate might:
- trim strings automatically
- save values to preferences
- validate input
- log every change
- connect properties to a framework object
Cleaner APIs
Instead of this:
Common Mistakes
1. Thinking by always means inheritance or copying
It does not copy a value and it does not mean subclassing.
In property declarations, by means the property is delegated.
2. Assuming the property has a normal backing field
A delegated property may not use a regular backing field in the way a normal property does. The delegate controls storage and behavior.
3. Forgetting that var needs both get and set support
Broken idea:
class ReadOnlyDelegate {
operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): String {
return "hello"
}
}
var name: String by ReadOnlyDelegate()
This fails because var requires setValue(...) too.
Fix:
- use
val, or - implement
setValue(...)
Comparisons
Delegated property vs normal property
| Feature | Normal property | Delegated property |
|---|---|---|
| Storage | Usually stored directly in the class | Often stored/managed by another object |
| Custom behavior | Manual getter/setter | Reusable delegate logic |
| Boilerplate | Can grow quickly | Often shorter |
| Read/write interception | You write it yourself | Delegate handles it |
by vs = in property declarations
| Syntax | Meaning |
|---|---|
var x = 10 | Store the value directly in the property |
Cheat Sheet
Quick syntax
val name: Type by delegate
var name: Type by delegate
What by means
- Delegate property behavior to another object
- Reads call
getValue(...) - Writes call
setValue(...)forvar
Delegate requirements
For val
operator fun getValue(thisRef: Any?, property: KProperty<*>): Type
For var
operator fun getValue(thisRef: Any?, property: KProperty<*>): Type
operator fun
FAQ
What does the by keyword mean in Kotlin?
In many contexts, by means delegation. For properties, it means another object handles getting and setting the property value.
Is by the same as assigning a value?
No. = stores a value directly. by connects the property to a delegate object that controls access.
Why is by common in Android Kotlin code?
Android code often needs lazy setup, state observation, and delayed initialization. Delegated properties make those patterns shorter and cleaner.
What is a delegated property in Kotlin?
A delegated property is a property whose behavior is implemented by another object through getValue and optionally setValue.
What happens when I use Delegates.notNull()?
The property must be assigned before you read it. If you read it too early, Kotlin throws an exception.
Can I create my own delegate?
Yes. You can write a class with operator fun getValue(...) and operator fun setValue(...) and use it with by.
Mini Project
Description
Build a small Kotlin class that tracks an app setting using delegated properties. This project demonstrates how by can add behavior to a property without writing manual getters and setters every time. You will use an observable delegate so changes are logged automatically.
Goal
Create a settings class where property changes are observed and printed whenever the value is updated.
Requirements
- Create a Kotlin class named
AppSettings. - Add a mutable property named
themeusingby Delegates.observable. - Start the property with the value
"light". - Print the old and new values whenever
themechanges. - In
main, create anAppSettingsobject and change the theme at least twice.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.
Android Foreground Service Notification Channels in Kotlin
Learn why startForeground fails on Android 8.1 and how to create a valid notification channel for foreground services in Kotlin.