Миграция Android-приложения с Java на Kotlin
Мы видим, как в репозиториях с десятками тысяч строк Java-кода команды застревают на этапе перехода на Kotlin. Google официально объявил, что новые Jetpack API — Paging 3, DataStore, WorkManager с корутинами, Jetpack Compose — получают Kotlin-first surface Google I/O 2019. Технически из Java их можно вызвать, но с таким количеством адаптеров и workaround'ов, что продуктивность падает. В типичном проекте 30% кода занимают геттеры, сеттеры и null-check'и — при миграции на Kotlin этот объём сокращается в 2–3 раза. Но автоконвертер Android Studio даёт лишь синтаксический перевод, а не архитектурный. Мы поможем вам мигрировать без остановки разработки и без потери стабильности. Свяжитесь с нами для предварительной оценки объёма работ.
Почему нельзя просто нажать «Convert Java File to Kotlin»
Android Studio умеет конвертировать Java-файлы в Kotlin автоматически. Результат — технически компилируется. Но это не Kotlin, это транслитерация Java на синтаксис Kotlin:
-
varвезде вместоval— нет immutability -
!!на каждой null-ссылке —NullPointerExceptionпросто переименован вKotlinNullPointerException - Нет data classes — те же POJO с геттерами через
field.get() -
objectи companion objects отсутствуют — static-методы болтаются как extensions - Coroutines нет — остаётся AsyncTask или RxJava
- Лямбды выглядят как Java 8 лямбды, но без
SAM conversionдля пользовательских интерфейсов
Такой код не даёт никаких преимуществ Kotlin, только добавляет путаницу. Автоконвертер — инструмент для начала, не для финала.
Как выглядит правильная миграция
Инвентаризация перед стартом
Первый шаг — полный аудит кодовой базы: количество классов по типам (Activity, Fragment, ViewModel, Repository, Model, Util), покрытие тестами, список активно разрабатываемых модулей vs стабильных, зависимости от Kotlin-несовместимых паттернов (например, finalize(), определённые паттерны с static inner classes).
На основе аудита строится план: какие файлы конвертируем в первую очередь, какие трогаем в последнюю, где параллельная разработка на Java идёт во время миграции.
Стратегия «снизу вверх»
Начинаем с классов без Android-зависимостей: модели данных, утилиты, константы. Java POJO с полями, геттерами и сеттерами превращается в Kotlin data class — это моментальная выгода: equals(), hashCode(), toString(), copy() бесплатно.
// Было: Java POJO, 60 строк с геттерами/сеттерами // Стало: data class UserProfile( val id: Long, val name: String, val email: String, val avatarUrl: String? = null ) Потом переходим к Repository-слою. Здесь ключевое решение — как обращаться с async-кодом. Если в проекте был RxJava, возможны два пути: оставить RxJava (Kotlin с RxJava работает прекрасно) или мигрировать на coroutines + Flow. Второй путь правильнее стратегически, но дороже в моменте. Для активно развивающихся репозиториев делаем coroutines; для стабильных модулей без изменений — оставляем RxJava до следующего большого рефакторинга.
Как мигрировать с LiveData на StateFlow
ViewModel-слой: LiveData → StateFlow + SharedFlow. Это не обязательный шаг, LiveData работает и в Kotlin, но StateFlow ведёт себя предсказуемее — нет магии с LifecycleOwner, нет observeForever утечек, нет setValue vs postValue путаницы. Замена происходит в три этапа: меняем тип поля, адаптируем подписки во фрагментах, обновляем тесты.
Activity и Fragment мигрируем последними. Там больше всего зависимостей, больше всего legacy-кода, и ошибки там дороже всего.
Работа с Java-Kotlin interop
Пока миграция не завершена, Java и Kotlin классы живут рядом. Kotlin вызывает Java без проблем. Java вызывает Kotlin — нужны аннотации:
-
@JvmStaticдля companion object методов, которые нужны из Java -
@JvmFieldдля полей без геттеров -
@JvmOverloadsдля функций с default parameters -
@Throws(IOException::class)если Kotlin-функция бросает checked exceptions
Игнорирование этих аннотаций — частая причина того, что автоконвертированный код не компилируется из соседних Java-файлов.
Тестирование в процессе миграции
Каждый конвертированный класс должен проходить существующие тесты без изменений — это гарантия, что конвертация не сломала логику. Если тестов не было — это момент их написать, до конвертации, пока логика понятна из Java-кода. Используем JUnit5 + MockK (для Kotlin-классов) или Mockito (если нужна совместимость с Java-тестами).
CI должен гонять тесты на каждый PR. Миграция без CI — это хаос: невозможно отследить, какой именно коммит сломал логику.
Пример полной конвертации одного файла
Допустим, у нас есть Java-класс UserRepository с методами, использующими Callback. После миграции на Kotlin с корутинами он становится:
class UserRepository(private val api: UserApi) { suspend fun getUser(id: Long): Result<User> = runCatching { api.getUser(id) } } Что ещё меняется попутно
При миграции разумно попутно решать накопленный технический долг: заменить AsyncTask (deprecated с API 30) на coroutines, перейти с SharedPreferences на DataStore, обновить Retrofit до версии с Kotlin suspend-функциями вместо Call<T>.
Но «попутно» не значит «всё сразу». Каждое такое изменение — риск регрессии. Составляем явный список «что делаем в рамках миграции», всё остальное — в backlog следующих спринтов.
Приоритет модулей при миграции
| Модуль | Приоритет | Обоснование |
|---|---|---|
| Модели и утилиты | Высокий | Нет зависимостей от фреймворка, безопасно конвертировать |
| Репозитории | Средний | Зависит от async-библиотеки, требуется рефакторинг |
| ViewModel | Средний | LiveData → StateFlow, тесты переписывать |
| Activity/Fragment | Низкий | Много зависимостей, ошибки дорогие |
Что входит в работу по миграции
- Аудит кодовой базы: оценка объёма, тестового покрытия, сложных мест
- План поэтапной конвертации с приоритетами и сроками
- Написание тестов для критических модулей до конвертации
- Ручная доработка архитектуры (coroutines, data classes, null safety)
- Обучение команды Kotlin-паттернам и новым API
- Поддержка post-migration: code review, доработка interop, оптимизация производительности
Сроки
Зависят от объёма кодовой базы, покрытия тестами и того, идёт ли параллельная разработка новых фич.
| Кодовая база | Покрытие тестами | Оценка |
|---|---|---|
| до 20 000 строк Java | хорошее (>60%) | 2-4 недели |
| 20 000 – 60 000 строк | частичное | 4-8 недель |
| 60 000+ строк | низкое | 2-4 месяца |
Оценка уточняется после аудита. Стоимость рассчитывается индивидуально.
Миграция — инвестиция. Команда, которая работает на Kotlin с coroutines и StateFlow, закрывает задачи быстрее, чем та же команда на Java с RxJava. Не потому что Kotlin магически лучше, а потому что меньше бойлерплейта, лучше инструменты анализа (KSP vs KAPT, lint-правила Kotlin), и библиотечная экосистема больше не сопротивляется. Пишите — получите консультацию специалиста и предварительную оценку вашего проекта.
Мы — команда с 7-летним опытом разработки на Android, реализовали более 30 проектов миграции с Java на Kotlin. Закажите аудит кода — и мы подготовим детальный план перехода.







