Implements observable values and signals for Kotlin. Observables let you connect callbacks which are called in response to various events. Observable values addionally track a value.
val items = ObservableStream
.of(1, 2, 3) // 1, 2, 3
.map { it + 1 } // 2, 3, 4
.filter { it > 2 } // 3, 4
items.connect { item ->
println("Got $item")
}
//> Got 3
//> Got 4
////////////////////////////////////////////
val value = MutableObservableValue.of(3)
value.connect { newValue ->
println("Got $newValue")
}
value.currentValue = 2
//> Got 2Check out the releases, or using a build system...
repositories {
// ...
maven { url = uri("https://jitpack.io") }
}
dependencies {
implementation("me.exerro:observables-kt:1.2.0")
}<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>me.exerro</groupId>
<artifactId>observables-kt</artifactId>
<version>1.2.0</version>
</dependency>The library is centred around three interfaces:
Observable- something which you can connect callbacks to.ObservableStream- an extension ofObservable, specialised for streams of values. Can be mapped, filtered, etc.ObservableValue- an extension ofObservableStreamwhich also holds a current value.
When a callback is connected, an ObservableConnection is returned which can be
used to disconnect the callback later. Multiple connections can be joined using
ObservableConnection.join to form a single connection.
An ObservableStream is a stream of values which can be connected to. Any value
that flows "through this stream" is passed to all connected callbacks. Using
map, filter, flatMap, and fold will return a new stream with the
operation applied. For example,
ObservableStream
.of(1, 2, 3, "hello") // 1, 2, 3, "hello"
.filterIsInstance<Int>() // 1, 2, 3
.map { it - 1 } // 0, 1, 2
.filter { it > 0 } // 1, 2
.flatMap { v -> List(v) { v } } // 1, 2, 2
.fold(3) { a, b -> a + b } // [3], 4, 6, 8
.connect(::println)
//> 4
//> 6
//> 8A signal is a type of ObservableStream and is similar to an event. As with
ObservableStreams, any connected functions (callbacks) will be called when the
signal is "emitted".
Some variants of signals take parameters. Parameters are provided to emit and
passed to the connected functions.
You can create signals with the ObservableSignal.create*Signal and
ObservableSignal.create*SignalOf methods, for example:
val (stream, emit) = ObservableSignal.createSignal<Int>()
stream.connect { value ->
println("Got $value")
}
emit(3)
//> Got 3The returned stream is a regular ObservableStream.
Signals are all thread-safe.
An ObservableValue is a wrapper around a value which also implements
ObservableStream - meaning you can connect to changes of the value.
There is a specialised interface MutableObservableValue which allows you to
set the value, along with providing some helpful constructors.
ObservableValues can act as property delegates, making the following possible:
val value = MutableObservableValue.of(0)
var currentValue: Int by value
println(currentValue)
//> 0
value.connect { newValue ->
println("Changed to $newValue")
}
currentValue = 1
//> Changed to 1