Pragmatic AI-Driven Workflows: Refactoring Legacy Kotlin Code with Gemini in Android Studio A developer outlines a multi-stage workflow for using Gemini in Android Studio and AI coding agents to migrate legacy Android codebases from RxJava and XML Views to Kotlin Coroutines, StateFlow, and Jetpack Compose. The approach breaks refactoring into isolated steps — converting RxJava observables to Coroutines/Flow, extracting imperative View state into a single immutable UI state object, migrating XML layouts to Compose, and generating comparative unit tests — rather than prompting the AI to convert entire files at once, which the author says causes hallucinated state hoisting, broken lifecycle handling, and dropped business logic. Maintaining legacy Android codebases often feels like taking care of an ancient engine while driving on a highway. Thousands of production apps still rely on a mix of Java/Kotlin code, imperative XML layouts, and complex RxJava reactive streams. While Jetpack Compose, Kotlin Coroutines, and StateFlow have become the modern standard for Android development, refactoring millions of lines of legacy code manually is time-consuming, repetitive, and prone to regressions. With the integration of Gemini in Android Studio and modern coding agents, Android engineers have a practical assistant to accelerate codebase modernization. However, handing full control to AI often leads to unmaintainable code or subtle runtime bugs. In this guide, we will explore a practical, step-by-step workflow for leveraging Gemini and AI coding agents to refactor legacy RxJava and XML View components into clean, idiomatic Jetpack Compose and Coroutines — without sacrificing safety or application stability. The Refactoring Strategy: Human Specs, AI Translates A common mistake developers make when using AI coding assistants is pasting an entire file and prompting: “Convert this to Compose and Coroutines.” This approach often results in hallucinated state hoisting, broken lifecycle handling, or dropped business logic. A far more effective workflow follows a multi-stage migration pipeline: Isolate Business Logic: Convert RxJava observables to Coroutines and Flow. Isolate UI State: Extract imperative View states into a single immutable UI state object. Migrate UI Layer: Convert Layout XML to Jetpack Compose components. Automate Verification: Use AI to generate comparative unit tests for the before-and-after logic. Let’s walk through this process using a representative legacy component: a user profile loader with search filtering and error handling. Step 1: Converting Legacy RxJava to Kotlin Coroutines and Flow Consider this typical legacy ViewModel snippet written with RxJava 2/3 and BehaviorSubject: // Legacy ViewModel using RxJava class LegacyUserProfileViewModel private val userRepository: UserRepository : ViewModel { private val compositeDisposable = CompositeDisposable val userStateSubject = BehaviorSubject.create