Observables in a remote interface are reactive streams of Event instances in Kotlin that, when connected to a Web Frame, can push data to the web layer. They are implemented with Asynchronous Flows, a powerful coroutine-based reactive programming library built by the Kotlin team , which means they are instances of Flows.

Examples

Observables can be declared any number of ways. The following examples are for a remote observable that sends events every time the network connection changes.

Declared as a class property

class Network {
    val visible = MutableSharedFlow<Event>()
}

Declared as a variable

val networkConnection = MutableSharedFlow<Event>()

Web Frame Configuration

For the following example, we’ll be using an observable declared like the following:

val networkConnection = MutableSharedFlow<Event>()

The observable reference can be passed directly to the Web Frame configuration.

Although you can add an instance of MutableSharedFlow directly to the Web Frame configuration, it is a good idea to convert it to an immutable flow first by using .asSharedFlow().

val configuration = WebFrame.Configuration(
    baseUrl = ...
    functions = ...
    observables = mapOf(
        "networkConnection$": networkConnection.asSharedFlow()
    ),
)

Observables must end in a dollar sign ($) to denote a reactive property, as popularized by Cycle.js. This isn’t merely convention—the dollar sign is how ProxyClient knows it’s an observable, not a function.

Kotlin API

Event

Remote observables must emit Event objects, which represent a single value sent to the web layer.

Constructors

Event(val data: JsonElement)

Create an Event object with arbitrary data.

Data must be JSON content on Android. One delightful way of creating arbitrary JSON content is by using the buildJsonObject helper from the KotlinX Serialization library:

val event = Event(buildJsonObject {
    put("type", "wifi")
})
inline fun <reified T> Event(json: T)

Technically not a constructor, this function can be used to instantiate Event objects with any serializable object.

The easiest way to make a class serializable is by annotating it with @Serializable from the KotlinX Serialization library:

import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class Connection(val type: String)

Then, objects can be passed to this constructor directly:

val event = Event(Connection("wifi"))

This constructor will throw an error if encoding fails (highly unlikely).

This function uses Json.encodeToJsonElement under the hood to serialize almost any data type: strings, booleans, ints, doubles, as well as any instances of classes annotated with @Serializable. For more information, see the docs for KotlinX Serialization.