Reactive Programming in Kotlin: RxKotlin Library and Coroutines

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Reactive Programming in Kotlin: From RxKotlin to Coroutines

Reactive programming is a paradigm focused on asynchronous processing of data streams and propagation of changes. In the Kotlin ecosystem, this concept is implemented in two main ways: through the RxKotlin library (reactive extensions for Kotlin based on RxJava) and through the built-in coroutines mechanism with Flow. In this article, we will thoroughly examine both approaches, their features, and usage examples.



What is Reactive Programming?

The main idea of reactive programming is to work with data as continuous streams. Instead of requesting data and waiting for a response, you subscribe to a stream and react to each new event. This is especially useful for UI applications, handling user input, network requests, and working with databases.



The RxKotlin Library

RxKotlin is a wrapper over RxJava that adds convenient extensions for Kotlin, such as lambdas, extension functions, and null-safety support. The main types:

  • Observable<T> — a stream that can emit from 0 to N elements and complete with an error or successfully.
  • Single<T> — a stream that emits exactly one element or an error.
  • Flowable<T> — a stream with backpressure support (managing consumption speed).
  • Completable — a stream that only completes (success/error) without data.


RxKotlin Example

import io.reactivex.rxjava3.core.Observableimport io.reactivex.rxjava3.schedulers.Schedulers

fun main() { val observable = Observable.create<String> { emitter -> emitter.onNext("Hello") emitter.onNext("from") emitter.onNext("RxKotlin") emitter.onComplete() }

observable .subscribeOn(Schedulers.io()) .observeOn(Schedulers.single()) .subscribe( { value -> println("Received: $value") }, { error -> println("Error: ${error.message}") }, { println("Stream completed") } )

Thread.sleep(1000) // Wait for async operations to complete}

In this example, an Observable is created that emits three strings and completes. The subscribeOn and observeOn operators manage execution threads.



Coroutines and Flow in Kotlin

Starting with Kotlin 1.3, coroutines became part of the language, and Flow (introduced in 1.3.70) is a reactive stream fully integrated with coroutines. Advantages over RxKotlin:

  • Less overhead (lightweight coroutines vs Java threads).
  • Natural integration with suspend functions.
  • Support for structured concurrency (automatic cancellation when scope completes).
  • Cleaner syntax without callbacks.


Flow Example

import kotlinx.coroutines.*import kotlinx.coroutines.flow.*

fun main() = runBlocking { val flow = flow { for (i in 1..5) { delay(100) // Simulate async work emit(i) // Emit element } }

flow .map { it * it } // Transformation .catch { e -> println("Error: $e") } .collect { value -> println("Square: $value") }}

Flow is lazy: data starts being generated only when collect is called. Operators like map, filter, flatMapConcat work the same as in Rx.



Comparison of RxKotlin and Flow

Recommendations

Characteristic RxKotlin Flow + Coroutines
Dependencies