Как стать автором
Обновить
0

Как писать и переиспользовать код на «‎чистом» Kotlin. Заметки Android-разработчика

Время на прочтение5 мин
Количество просмотров3.4K


Как собрать в прямом эфире 17 000 зрителей? Значит, рецепт такой. Берем 15 актуальных IT-направлений, зовем зарубежных спикеров, дарим подарки за активность в чате, и вуа-ля — крупнейший в Украине и восточной Европе онлайн-ивент готов. Именно так прошла ежегодная мультитул конференция NIXMultiConf.

Под слоганом «айтишникам — от айтишников» эксперты из Украины, Беларуси, России, Великобритании и Германии поделились опытом и рассказали о новинках индустрии. Полезно было всем — дизайнерам, девелоперам, тестировщикам и менеджерам. И теперь делимся инсайтами с вами. По мотивам докладов экспертов NIX продолжаем серию материалов на самые актуальные темы.

В новой статье Вадим Савченко, Android developer в NIX, рассказывает о Kotlin и возможностях использования кода для нескольких целевых платформ.

Хочешь знать больше — смотри конференцию на YouTube-канале


Привет! Я — Вадим Савченко, Android developer в NIX. Коллеги наверняка знают: переиспользовать код — обычная практика для любого программиста. Этот подход ускоряет процесс разработки и уменьшает вероятность ошибок. Когда видишь лаконичный код, лучше фокусируешься на бизнес-логике продукта. Именно эту цель мы с командой преследовали, когда впервые взялись за Kotlin Multiplatform Mobile. На конференции NIXMulticonf я презентовал результат нашей работы. А в этой статье подробнее расскажу, как использовать код для нескольких целевых платформ и почему знание Kotlin — ценный навык.

Как часто водится на аутсорсе, заказчик хочет готовое решение быстро, качественно и от одного разработчика. Kotlin Multiplatform Mobile (далее — КММ) экономит время и усилия и помогает достигнуть желаемого результата. Команда NIX давно успешно использует Kotlin в коммерческих проектах. На этот раз мы решили пойти дальше и узнать, какие возможности дает КМM.

Суть подхода заложена в слогане на официальном сайте КММ: Save time and effort by writing the business logic for your iOS and Android apps just once. Мы можем создавать модули с общим кодом и подключать их к разным нативным приложениям на Android и IOS.

Однако «‎чистый» Kotlin не так прост, как кажется. Нетрудно отказаться от Android импортов в слое бизнес-логики, но гораздо сложнее свыкнуться с мыслью, что Java импортов тоже не должно быть. Мы посмотрели на KMM в разрезе Clean Architecture. Здесь есть явное отделение слоя бизнес-логики от остальной части приложения (слой Domain). Разбиение на слои мы сделали с помощью модулей. Так проще проконтролировать, чтобы лишний импорт и платформозависимый код не попали, куда не следует. Получили три модуля — Presentation, Domain, Data:

  • Presentation — это модуль с презентационной логикой и вьюшками;
  • Domain — бизнес-логика;
  • Data — репозитории и датасорсы.

Domain и есть наш KMM модуль, написанный на «‎чистом» Kotlin. Собрать его без проблем можно под IOS и Android. Presentation и Data — платформозависимые модули и не могут быть переиспользованы… Но это не точно. Мы решили выяснить, могут ли Data и Presentation стать KMM модулями на основе Pure Kotlin.

Сначала из Presentation выделили еще один модуль UI и закинули в него Views, Activities, Fragments. В Presentation же оставили MVP контракты и реализации презенторов. Зачастую в них можно обойтись без Android импортов. Затем из Data выделили Infrastructure. Здесь у нас DataSources и реализации Repositories, требующие Java или Android импортов. В Data остаются модельки, которыми оперирует приложение, и контракты Repositories. В итоге наши догадки оправдались: Data и Presentation тоже готовы к переиспользованию.


KMM позволяет сделать мультиплатформенными Infrastructure и View, но с ними дела обстоят сложнее. Создадим еще один простой KMM модуль для логирования. После этого вместо привычного java -> main у вас появится commonMain. androidMain и iosMain. Как же их использовать?



//Common
expect class MultiLogger() {

   fun logError()
}

//Android
actual class MultiLogger {

   actual fun logError() {
       Log.e("ERROR", "ERROR ANDROID")
   }
}

//IOS
actual class MultiLogger {

   actual fun logError() {
      println("ERROR IOS")
   }
}

В commonMain лежит «‎чистый» Kotlin-код. В случае с Domain весь код будет лежать здесь, а androidMain и iosMain нам вообще не понадобятся. Так как мы хотим, чтобы для Аndroid логирование происходило через стандартный Log, а не println(), нам нужны androidMain и iosMain. Для реализации в commonMain создали класс MultiLogger и обозначили его ключевым словом еxpect. В androidMain объявили класс MultiLogger и реализовали лог с помощью привычного нам Log. В iosMain используем println и надеемся, что он нас устроит :).

По аналогии с логером то же самое можно сделать с UI модулем и Infrastructure. Задача такого разбиения — отделить то, что может быть собрано под Android и IOS и в будущем легко реализовано на каждой из этих платформ. Если не хотите вручную писать View отдельно для двух платформ, воспользуйтесь готовыми решениями. Например, moko-widgets. Так же и с Data слоем, есть библиотека moko-permissions, которую можно взять для ваших репозиториев и не прибегать к expect и actual.

Оказалось, не всё так гладко


Когда мы впервые столкнулись с Kotlin, нас ждало несколько сюрпризов. Расскажу вам о них, чтобы вы были ко всему готовы.

Из минусов — мультиплатформенные проекты требуют новейшей версии системы сборки Gradle. Переход к старым проектам затрудняется. Если вы уже переключились на мультиплатформу, но через какое-то время вам надо вернуться в прошлый коммерческий проект, сделать это будет сложно. Gradle вечно что-то кеширует, приходится постоянно чистить кеш, но чаще это не помогает. Ок, переустанавливаем. Но на все это уходит слишком много времени.

Кроме того, нам пришлось вручную формировать пакеты и структуры папок под три Source-набора: Android main, iOS main и Common main. Также было неудобно самим создавать build.gradle.kts и прописывать в них пути к исходникам.

Также были проблемы с общением между модулями. Студия подсвечивала все импорты и сущности из соседних модулей красным и не видела их, хотя все успешно собиралось и работало.

Если до этого момента вы успешно откладывали знакомство с Coroutines, здесь уже без них никак. С помощью Корутинов на Kotlin пишут асинхронный, неблокирующий код. У нас с ними все было ОК. Но коллеги рассказывали, что иногда Coroutines могут зависнуть в iOS по непонятным причинам, и это сложно предотвратить и контролировать. Насколько я знаю из новейших источников, этот момент пофиксили. Но есть другая проблема — iOS код может выдавать ошибки, которые превращаются в базовые iOS-ные.

Сейчас почти все проблемы ушли. Вы можете использовать последнюю версию android studio, и все будет прекрасно работать. Также Kotlin Multiplatform Mobile Plugin существенно упрощает создание новых мультиплатформенных проектов и поддержку текущих и даже позволяет дебажить код, собранный под IOS.

Подводя итоги, хотелось бы сказать, что все Android-разработчики давно привыкли использовать Kotlin. Круто, что совсем немного изменив нашу структуру модулей, мы можем получить код, который будет переиспользован. Так что давайте пробовать, заводить тикеты о проблемах, с которыми сталкиваемся, поднимать комьюнити и учиться на ошибках друг друга.
Теги:
Хабы:
+5
Комментарии0

Публикации

Информация

Сайт
www.nixsolutions.com
Дата регистрации
Дата основания
1994
Численность
1 001–5 000 человек

Истории