new-silvermoon/rxjava-to-coroutines-migration
Guide and execute the migration of asynchronous code from RxJava to Kotlin Coroutines and Flow. Use this skill when a user asks to convert RxJava (Observables, Singles, Completables, Subjects) to Coroutines (suspend functions, Flows, StateFlows).
npx skills add https://github.com/new-silvermoon/awesome-android-agent-skills --skill rxjava-to-coroutines-migration
A specialized skill designed to safely and idiomatically refactor Android or Kotlin codebases from RxJava to Kotlin Coroutines and Flow.
When migrating RxJava components to Kotlin Coroutines, use the following standard mappings:
Single<T> -> suspend fun ...(): TMaybe<T> -> suspend fun ...(): T?Completable -> suspend fun ...()Observable<T> -> Flow<T>Flowable<T> -> Flow<T>PublishSubject<T> -> MutableSharedFlow<T>MutableSharedFlow(extraBufferCapacity = ...) if buffering is needed.BehaviorSubject<T> -> MutableStateFlow<T>ReplaySubject<T> -> MutableSharedFlow<T>(replay = N)Schedulers.io() -> Dispatchers.IOSchedulers.computation() -> Dispatchers.DefaultAndroidSchedulers.mainThread() -> Dispatchers.MainsubscribeOn and observeOn are typically replaced by withContext(Dispatcher) or flowOn(Dispatcher) for Flows.map -> mapfilter -> filterflatMap -> flatMapMerge (concurrent) or flatMapConcat (sequential)switchMap -> flatMapLatestdoOnNext / doOnSuccess -> onEachonErrorReturn / onErrorResumeNext -> catch { emit(...) }startWith -> onStart { emit(...) }combineLatest -> combinezip -> zipdelay -> delay (suspend function) or onEach { delay(...) }subscribe() -> collect {} (for Flows) or direct invocation (for suspend functions) inside a CoroutineScope.Disposable.dispose() -> Job.cancel()CompositeDisposable.clear() -> Cancel the parent CoroutineScope or Job.suspend functions for one-shot operations, and Flow for streams.map or onEach block..subscribe(...) with launch { ... } and .collect { ... } in the ViewModel or Presenter. Ensure the launch is tied to the correct lifecycle scope (e.g., viewModelScope).onError blocks with try/catch around suspend functions, or .catch { } operators on Flows..subscribeOn() and .observeOn(). Use withContext where necessary, or .flowOn() to change the context of the upstream flow.RxJava:
fun getUser(id: String): Single<User> { ... }
disposable.add(
getUser("123")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ user ->
view.showUser(user)
}, { error ->
view.showError(error)
})
)
Coroutines/Flow:
suspend fun getUser(id: String): User { ... } // Internally uses withContext(Dispatchers.IO) if needed
viewModelScope.launch {
try {
val user = getUser("123")
view.showUser(user)
} catch (e: Exception) {
view.showError(e)
}
}
suspend functions instead of Flow unless you actually have a stream of multiple values over time. Single and Completable almost always become suspend functions.StateFlow in ViewModels to expose state to the UI instead of BehaviorSubject or LiveData.repeatOnLifecycle or flowWithLifecycle in the UI layer when collecting Flows to avoid background work when the view is not visible.Take new-silvermoon/rxjava-to-coroutines-migration from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.