Миграция Android-приложения с Java на Kotlin

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Миграция Android-приложения с Java на Kotlin
Сложная
от 2 недель до 3 месяцев
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Миграция Android-приложения с Java на Kotlin

В репозитории 80 000 строк Java-кода, команда давно знает все грабли, продукт работает — и тут Google объявляет, что новые Jetpack API разрабатываются только для Kotlin, а часть существующих получает Kotlin-first surface. Paging 3, DataStore, WorkManager с корутинами, Jetpack Compose — всё это технически доступно из Java, но с такими адаптерами и обходными путями, что разработка превращается в борьбу с инструментами вместо решения задач.

Миграция с Java на Kotlin — не переписывание с нуля. Это постепенный процесс, который при правильной организации не останавливает разработку продукта и не ломает стабильность.

Почему нельзя просто нажать «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 до следующего большого рефакторинга.

ViewModel-слой: LiveDataStateFlow + 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 — это хаос: невозможно отследить, какой именно коммит сломал логику.

Что ещё меняется попутно

При миграции разумно попутно решать накопленный технический долг: заменить AsyncTask (deprecated с API 30) на coroutines, перейти с SharedPreferences на DataStore, обновить Retrofit до версии с Kotlin suspend-функциями вместо Call<T>.

Но «попутно» не значит «всё сразу». Каждое такое изменение — риск регрессии. Составляем явный список «что делаем в рамках миграции», всё остальное — в backlog следующих спринтов.

Сроки

Зависят от объёма кодовой базы, покрытия тестами и того, идёт ли параллельная разработка новых фич.

Кодовая база Покрытие тестами Оценка
до 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), и библиотечная экосистема больше не сопротивляется.