Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Kotlin observable delegation is a property delegation mechanism provided by the standard library (kotlin.properties.Delegates) that intercepts property assignments to execute custom callback logic. It abstracts the boilerplate of custom setters by routing property mutations through a delegated ReadWriteProperty instance. The Kotlin standard library provides two primary functions for observable delegation: Delegates.observable and Delegates.vetoable. Both functions take an initial value and a handler lambda, returning an ObservableProperty<T> that manages the property’s backing field.

Delegates.observable

The observable function executes its callback after the assignment has been made to the backing field. Syntax:
inline fun <T> observable(
    initialValue: T,
    crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit
): ReadWriteProperty<Any?, T>
Implementation:
import kotlin.properties.Delegates

class StateManager {
    var status: String by Delegates.observable("IDLE") { property, oldValue, newValue ->
        // This block executes immediately after the backing field is updated.
        println("${property.name} transitioned: $oldValue -> $newValue")
    }
}

Delegates.vetoable

The vetoable function executes its callback before the assignment is committed to the backing field. The lambda must return a Boolean. If the lambda evaluates to true, the mutation proceeds. If it evaluates to false, the assignment is intercepted and discarded, leaving the backing field unmodified. Syntax:
inline fun <T> vetoable(
    initialValue: T,
    crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean
): ReadWriteProperty<Any?, T>
Implementation:
import kotlin.properties.Delegates

class Configuration {
    var threshold: Int by Delegates.vetoable(10) { property, oldValue, newValue ->
        // The assignment only succeeds if this expression evaluates to true.
        newValue >= oldValue 
    }
}

Internal Mechanics

When you use the by keyword with these delegates, the Kotlin compiler generates a hidden reference to the ObservableProperty object and routes all getValue and setValue calls through it.
  1. KProperty<*>: The first parameter of the callback provides reflection-based metadata about the delegated property. It is most commonly used to access property.name.
  2. ObservableProperty<T>: Both observable and vetoable instantiate an anonymous subclass of ObservableProperty<T>.
    • In observable, the subclass overrides the afterChange method. The base setValue implementation updates the internal value, then invokes afterChange.
    • In vetoable, the subclass overrides the beforeChange method. The base setValue implementation invokes beforeChange; it only updates the internal value if beforeChange returns true.
  3. Thread Safety: Neither Delegates.observable nor Delegates.vetoable are inherently thread-safe. If the delegated property is mutated concurrently from multiple threads, the callbacks and the backing field updates are subject to race conditions unless externally synchronized.
Master Kotlin with Deep Grasping Methodology!Learn More