Kotlin’s Explicit Backing Fields: A Cleaner Way to Work with MutableStateFlow
In Kotlin, it’s common to have a property that you expose to the outside world and a private property (or backing property) that holds the actual value. This pattern is widely used but comes with its verbosity and boilerplate, especially when dealing with read-only and mutable versions of structures like MutableLiveData
, MutableStateFlow
, etc.
In reactive programming with Kotlin coroutines, the StateFlow class is used to represent a stream of values that can be collected asynchronously. StateFlow has a mutable counterpart called MutableStateFlow, which allows updating the stream’s value from within the same scope.
However, exposing the MutableStateFlow directly as a public API is generally not recommended, as it would allow external code to modify the stream’s value unexpectedly. To address this, a common pattern is to use a private MutableStateFlow instance as a backing property and expose a read-only StateFlow view of it.
private val _city = MutableStateFlow("")
val city: StateFlow<String> get() = _city
In this example, _city
is a private MutableStateFlow
that holds the actual data. The public property city
provides a read-only view of this data . While this pattern works, it can be cumbersome, especially when dealing with multiple properties.
The Solution: Explicit Backing Fields
Kotlin 2.0(RC1) introduces Explicit Backing Fields, a feature that streamlines property definition. They allow you to create properties with private mutable backing fields and public read-only accessors in a single line.
Here’s how to rewrite the previous code with Explicit Backing Fields:
class SomeViewModel {
val city: StateFlow<String>
field = MutableStateFlow("")
fun updateCity(newCity: String) {
city.value = newCity // visible as MutableStateFlow, calling field
}
}
fun outside(vm: SomeViewModel) {
vm.city // visible as StateFlow, calling getter
}
The field
keyword declares a private backing field of type MutableStateFlow(private
is the default and the only allowed visibility for explicit backing fields), and the public city
property exposes a read-only StateFlow view of it. This syntax is more concise and makes the intent clearer.
Conclusion
Explicit Backing Fields offer a cleaner and more efficient way to manage state and expose read-only data streams in Kotlin. This feature simplifies your code, improves readability, and reduces boilerplate, making your Kotlin development experience smoother.