Делимся новостями, библиотеками, интересными кейсами по мобильной разработке с использованием kotlin multiplatform
Kotlin Multiplatform pinned «Делимся новостями, библиотеками, интересными кейсами по мобильной разработке с использованием kotlin multiplatform»
Первой новостью у нас будет очередной релиз кандидат библиотеки https://github.com/badoo/Reaktive
Интересно это в первую очередь тем, что это первая реализация Rx доступная в kotlin common коде, а ещё более интересно - в версии для kotlin/native поддерживается смена потоков. Один из разработчиков библиотеки рассказал детали в своем выступлении в Минске - https://youtu.be/2sxTUzG6HEA
#libs
Интересно это в первую очередь тем, что это первая реализация Rx доступная в kotlin common коде, а ещё более интересно - в версии для kotlin/native поддерживается смена потоков. Один из разработчиков библиотеки рассказал детали в своем выступлении в Минске - https://youtu.be/2sxTUzG6HEA
#libs
GitHub
GitHub - badoo/Reaktive: Kotlin multi-platform implementation of Reactive Extensions
Kotlin multi-platform implementation of Reactive Extensions - badoo/Reaktive
А из интересных кейсов вчера поднялась в kotlinlang.slack.com интересная тема - как включить в градле обе айос архитектуры так, чтобы IDE не ломалась.
Напомню что решение согласно документации котлина - активировать только одну из архитектур (x64 по умолчанию, а если передана переменная окружения SDK_NAME с значением iphoneos - то arm64) из-за чего компиляция под устройство доступна только из xcode и нет управления полноценного зависимостями (ведь зависимости то под конкретную архитектуру скомпилированы).
Были озвучены пара интересных хаков:
1. Создать iosX64 таргет с именем ios (таким образом получаем сорссет iosMain), а так же обычные iosX64 и iosArm64 с указанием dependsOn iosMain. Говорят так получаем единый код и корректную работу IDE
2. Хранить код в iosMain директории, а для Gradle и IDE создать две симлинки iosX64Main и iosArm64Main после чего IDE корректно видит actual классы и Gradle предоставляет отдельные таски сборки айос версии, без лишних тасок как в первом случае.
Подробнее можно ознакомиться тут https://kotlinlang.slack.com/archives/C3SGXARS6/p1568297037167500
#cases
Напомню что решение согласно документации котлина - активировать только одну из архитектур (x64 по умолчанию, а если передана переменная окружения SDK_NAME с значением iphoneos - то arm64) из-за чего компиляция под устройство доступна только из xcode и нет управления полноценного зависимостями (ведь зависимости то под конкретную архитектуру скомпилированы).
Были озвучены пара интересных хаков:
1. Создать iosX64 таргет с именем ios (таким образом получаем сорссет iosMain), а так же обычные iosX64 и iosArm64 с указанием dependsOn iosMain. Говорят так получаем единый код и корректную работу IDE
2. Хранить код в iosMain директории, а для Gradle и IDE создать две симлинки iosX64Main и iosArm64Main после чего IDE корректно видит actual классы и Gradle предоставляет отдельные таски сборки айос версии, без лишних тасок как в первом случае.
Подробнее можно ознакомиться тут https://kotlinlang.slack.com/archives/C3SGXARS6/p1568297037167500
#cases
С прошедшего в прошлом месяце droidcon NYC рекомендую ознакомиться в первую очередь с докладом о эффективной мультиплатформенной архитектуре. Это не очередной доклад про MV* а хороший разбор как привести две платформы к общему коду - подготовиться сначала разбив на модули, после чего выбрать в каком порядке делать подключение второй платформе к общим модулям (разобрано сразу несколько вариантов). Все наглядно с картинками и кодом
https://speakerdeck.com/rharter/effective-multiplatform-architecture
#slides
https://speakerdeck.com/rharter/effective-multiplatform-architecture
#slides
Speaker Deck
Effective Multiplatform Architecture
Building multiplatform apps requires thinking about architecture a little differently than their single platform counterparts. Individually, each platfo…
Второй пост из серии "kotlin multiplatform in five minutes" рассказывает о концепции expect/actual. Для тех кто хоть раз уже использовал этот механизм ничего нового в статье нет, остальным же может быть полезен (в целом как и документация на kotlinlang)
https://touchlab.co/expect-actuals-statements-kotlin-multiplatform/
#posts
https://touchlab.co/expect-actuals-statements-kotlin-multiplatform/
#posts
touchlab.co
Kotlin Multiplatform in Five Minutes or Less: Expect / Actuals Statements
Unlike other “cross platform” ecosystems, Kotlin is designed to embrace the native platform it is integrating with. expect/actual statements.
Продолжим "больную" тему многопоточности в kotlin/native. В прошлом посте я рассказал о библиотеке Reaktive от badoo, которая приносит Rx в общий код и переключение потоков в том числе.
Сегодня же хочется поделиться "народным" решением проблемы многопоточных корутин - https://github.com/Autodesk/coroutineworker
Данная библиотека позволяет выносить выполнение suspend функций на фоновый поток (либо запустить внутри suspend функции выполнение другого блока на фоновом потоке). Построена библиотека примерно так же как и Reaktive - лямбда, которая должна выполниться на фоновом потоке, автоматически замораживается, а с ней и все зависимости которые она имеет (поэтому очень важно не захватить случайно this или какой нибудь из объектов, иначе рассинхрон ThreadLocal копий объектов сломает логику приложения). Результат который выдается из лямбды тоже автоматически замораживается, поэтому модифицировать полученный объект сразу не получится - для модификации придется создавать копию.
#libs
Сегодня же хочется поделиться "народным" решением проблемы многопоточных корутин - https://github.com/Autodesk/coroutineworker
Данная библиотека позволяет выносить выполнение suspend функций на фоновый поток (либо запустить внутри suspend функции выполнение другого блока на фоновом потоке). Построена библиотека примерно так же как и Reaktive - лямбда, которая должна выполниться на фоновом потоке, автоматически замораживается, а с ней и все зависимости которые она имеет (поэтому очень важно не захватить случайно this или какой нибудь из объектов, иначе рассинхрон ThreadLocal копий объектов сломает логику приложения). Результат который выдается из лямбды тоже автоматически замораживается, поэтому модифицировать полученный объект сразу не получится - для модификации придется создавать копию.
#libs
GitHub
GitHub - Autodesk/coroutineworker: Kotlin Coroutine-based workers for native
Kotlin Coroutine-based workers for native. Contribute to Autodesk/coroutineworker development by creating an account on GitHub.
Пока нет горячих новостей продолжим обзор доступных библиотек. Не так давно появился плагин, который автоматически генерирует для корутин методы которые будут доступны на стороне iOS. Проблема с корутинами на айос не только в отсутствии многопоточности, но и в том что все suspend функции недоступны для вызова из swift (такой вид функций в swift не существует). А плагин при выставлении специальной аннотации автоматически сгенерирует код функции с калбеком, которая внутри уже вызывает suspend функцию. Тем кто хочет иметь доступ с натива до suspend функций - must have.
https://github.com/feilfeilundfeil/kotlin-native-suspend-function-callback
#libs
https://github.com/feilfeilundfeil/kotlin-native-suspend-function-callback
#libs
GitHub
GitHub - feilfeilundfeil/kotlin-native-suspend-function-callback: Kotlin Multiplatform compiler plugin to generate a callback implementation…
Kotlin Multiplatform compiler plugin to generate a callback implementation for suspended functions so they are visible from Kotlin Native - GitHub - feilfeilundfeil/kotlin-native-suspend-function-c...
Сегодня поделюсь недавно опубликованной презентацией доклада о kotlin multiplatform задевающей и сравнение с кроссплатформенными решениями, и создание приложения с стандартной функциональностью мобилок - работа с сетью, хранение данных локально, вывод данных пользователю. Основная ценность именно в наглядном и доступном примере - не "hello world", а с обычным функционалом мобильных приложений. В комплекте и сравнение техстека нативок и мультиплатформенной разработки, и сравнение языков, и отзывы айос разработчиков, и немного рекомендаций. Для тех кто с темой знакомится - рекомендую. Для тех кто уже разрабатывает на мультиплатформе - скорей всего нового ничего не будет (если только работа с sqldelight в новинку, ну и отзывы айосников).
https://speakerdeck.com/cmota/the-hitchhikers-guide-through-kotlin-multiplatform-extended
демо проект тут - https://github.com/cmota/droidconLX
#slides
https://speakerdeck.com/cmota/the-hitchhikers-guide-through-kotlin-multiplatform-extended
демо проект тут - https://github.com/cmota/droidconLX
#slides
Speaker Deck
The Hitchhikers Guide Through Kotlin Multiplatform Extended
Since the early days of mobile that we keep seeing new frameworks being designed to overcome one of the biggest challenges:
- How can I develop for both Android and iOS?
Although it’s initial promises, when we talk about performance, maintainability or…
- How can I develop for both Android and iOS?
Although it’s initial promises, when we talk about performance, maintainability or…
Обратим внимание на работу с датой и временем - в kotlin stdlib в версии kotlin 1.3.50 появились первые экспериментальные API для дальнейшей поддержки даты и времени в common коде. Это kotlin.time - https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/index.html
На данный момент в API присутствует только функционал замера продолжительности времени (что совсем не покрывает полноценные задачи в проектах), но это всего первый шаг.
А пока официальное API прорабатывается (https://github.com/Kotlin/KEEP/blob/durations/proposals/stdlib/durations-and-clocks.md) для решения реальных задач на проектах можно использовать:
* https://github.com/korlibs/klock - позволяет парсить строку в дату и обратно, имеет работу с часовыми поясами и получать текущее время с устройства;
* https://github.com/lightningkite/lokalize - включает в себя и даты и время и продолжительность, работу с локалью (рендер времени/даты в локали устройства). Но не содержит поддержки часовых поясов;
* https://github.com/icerockdev/moko-core - позволяет получить таймштамп, а так же запускать таймеры в общем коде;
* https://github.com/ktorio/ktor (а именно ktor-utils) - содержит GMTDate и парсер дат в GMT. поддержки часовых поясов конечно нет, все приводится при парсинге в GMT, и форматирования кастомного нет, но для сети может хватать;
* свой вариант expect/actual - если никакая из библиотек не подошла, можно написать свои функции expect/actual и заиспользовать java.time.* и NSDate, делая так, как сделали бы на платформах при чистой нативной разработке (пример был в недавней статье - https://touchlab.co/expect-actuals-statements-kotlin-multiplatform/).
#libs
На данный момент в API присутствует только функционал замера продолжительности времени (что совсем не покрывает полноценные задачи в проектах), но это всего первый шаг.
А пока официальное API прорабатывается (https://github.com/Kotlin/KEEP/blob/durations/proposals/stdlib/durations-and-clocks.md) для решения реальных задач на проектах можно использовать:
* https://github.com/korlibs/klock - позволяет парсить строку в дату и обратно, имеет работу с часовыми поясами и получать текущее время с устройства;
* https://github.com/lightningkite/lokalize - включает в себя и даты и время и продолжительность, работу с локалью (рендер времени/даты в локали устройства). Но не содержит поддержки часовых поясов;
* https://github.com/icerockdev/moko-core - позволяет получить таймштамп, а так же запускать таймеры в общем коде;
* https://github.com/ktorio/ktor (а именно ktor-utils) - содержит GMTDate и парсер дат в GMT. поддержки часовых поясов конечно нет, все приводится при парсинге в GMT, и форматирования кастомного нет, но для сети может хватать;
* свой вариант expect/actual - если никакая из библиотек не подошла, можно написать свои функции expect/actual и заиспользовать java.time.* и NSDate, делая так, как сделали бы на платформах при чистой нативной разработке (пример был в недавней статье - https://touchlab.co/expect-actuals-statements-kotlin-multiplatform/).
#libs
Kotlin
kotlin.time - Kotlin Programming Language
Сегодня заденем тему отладки, а именно - отладки библиотеки написанной на Kotlin в iOS. В отличие от flutter, react native, xamarin и подобных - для отладки кода скомпилированного kotlin/native не требуется никакой специфичный отладчик. Достаточно Xcode и встроенного в него lldb. Например, используя следующую команду можно строчке в kotlin файле поставить breakpoint:
b -f hello.kt -l 1
И при остановке на этом месте Xcode корректно выведет стектрейс, с понятным именованием kotlin функций, даже тех что находятся внутри stdlib. Для упрощения установки breakpoint'ов в Touchlab сделали специальный плагин для Xcode, позволяющий открыть kotlin файл и поставить breakpoint так же просто как в swift файле - нажав слева от строки в Xcode. Также поддержка точек останова есть и в AppCode от JetBrains (с установленным плагином Kotlin/Native).
Единственное неудобство - локальные переменные доступные в скоупе функции, где мы остановились, не доступны для вывода информации о них. Но используя специальный python скрипт для отладчика - можно считать и их. Подробнее в разделе Variable Inspection в документации про отладку kotlin/native.
Подробнее про отладку и Variable Inspection - https://github.com/JetBrains/kotlin-native/blob/master/DEBUGGING.md
Статья с обзором плагина для Xcode - https://medium.com/hackernoon/kotlin-xcode-plugin-64f52ff8dc2a
Новость о добавлении поддержки Kotlin/Native в AppCode - https://blog.jetbrains.com/kotlin/2019/04/kotlinnative-support-for-appcode-2019-1/
#tips
b -f hello.kt -l 1
И при остановке на этом месте Xcode корректно выведет стектрейс, с понятным именованием kotlin функций, даже тех что находятся внутри stdlib. Для упрощения установки breakpoint'ов в Touchlab сделали специальный плагин для Xcode, позволяющий открыть kotlin файл и поставить breakpoint так же просто как в swift файле - нажав слева от строки в Xcode. Также поддержка точек останова есть и в AppCode от JetBrains (с установленным плагином Kotlin/Native).
Единственное неудобство - локальные переменные доступные в скоупе функции, где мы остановились, не доступны для вывода информации о них. Но используя специальный python скрипт для отладчика - можно считать и их. Подробнее в разделе Variable Inspection в документации про отладку kotlin/native.
Подробнее про отладку и Variable Inspection - https://github.com/JetBrains/kotlin-native/blob/master/DEBUGGING.md
Статья с обзором плагина для Xcode - https://medium.com/hackernoon/kotlin-xcode-plugin-64f52ff8dc2a
Новость о добавлении поддержки Kotlin/Native в AppCode - https://blog.jetbrains.com/kotlin/2019/04/kotlinnative-support-for-appcode-2019-1/
#tips
Немного про подключение kotlin/native фреймворка в ios приложение. Есть несколько путей:
1. Добавить в ios проекте отдельный таргет-фреймворк, который не будет иметь какого либо исходного кода, но будет содержать специальную build phase, в которой будет происходить вызов gradle task компиляции фреймворка, после чего результат компиляции будет копироваться в директорию сборки xcode - туда, куда бы сам xcode скомпилировал фреймворк будь тут исходный код swift'а. Это самый старый вариант интеграции.
2. Добавить в ios проекте фреймворк как embed фреймворк, указывая где он будет находиться - директория должна быть всегда одна, даже для разных архитектур фреймворка. Далее добавить к проекту build phase, которая будет вызывать у gradle специальную таску. Задача таски - собрать фреймворк и положить его по тому пути, который был указан при добавлении фреймворка в проект. Таким образом нет никаких лишних таргетов. Этот подход описан в текущем туториале от JetBrains "Targeting iOS and Android with Kotlin Multiplatform".
3. Интеграция через CocoaPods используя плагин org.jetbrains.kotlin.native.cocoapods. Для айосников он будет самый удобный. В gradle потребуется добавить специальную конфигурацию плагина (по сути описание pod'а нашего) и плагин автоматически сгенерирует нам podspec. После чего в Podfile от iOS приложения мы просто ссылаемся на наш pod локальный и вся интеграция готова. Под капотом все работает примерно так же как первый и второй случай - создается специальный проект для pod'а, там нет исходного кода но есть embed framework который собирается специальной gradle таской, которая и скомпилирует и перенесет фреймворк по нужному пути. Есть у этого решения пара особенностей - во первых на момент pod install фреймворк должен быть уже скомпилирован, то есть в градле мы должны засинхать проект и запустить gradle task :podspec в нашем mpp проекте. Во вторых - из gradle проекта не видны таски, используемые в xcode build phase (syncFramework в особенности). То есть запустить перекомпиляцию с переносом фреймворка куда-надо из вне xcode нельзя. А еще плагин позволяет подключать iOSные pod'ы в kotlin/native (только те у которых есть objc биндинг).
4. Интеграция через CocoaPods но без плагина org.jetbrains.kotlin.native.cocoapods. Разница в том, что podspec файл один раз пишется и кладется рядом с проектом, а градл таски syncFramework добавляются отдельно к проекту (у нас в IceRock это делает наш mobile-multiplatform плагин) и доступны для запуска просто из IDE или gradle. Это дает больше прозрачности при разработке и полный контроль над самой build phase сборки фреймворка (мы например кеширование на проектах через shell скрипт дополнительное делаем, чтобы не запускать gradle лишний раз при сборках ios проекта - он очень долгий).
Туториал Targeting iOS and Android with Kotlin Multiplatform - https://play.kotlinlang.org/hands-on/Targeting%20iOS%20and%20Android%20with%20Kotlin%20Multiplatform/
Плагин CocoaPods - https://kotlinlang.org/docs/reference/native/cocoapods.html
Плагин mobile-multiplatform - https://github.com/icerockdev/mobile-multiplatform-gradle-plugin
Пример интеграции mobile-multiplatform плагина (пока у него нет ридми) - https://github.com/icerockdev/moko-mvvm/tree/master/sample
#tips
1. Добавить в ios проекте отдельный таргет-фреймворк, который не будет иметь какого либо исходного кода, но будет содержать специальную build phase, в которой будет происходить вызов gradle task компиляции фреймворка, после чего результат компиляции будет копироваться в директорию сборки xcode - туда, куда бы сам xcode скомпилировал фреймворк будь тут исходный код swift'а. Это самый старый вариант интеграции.
2. Добавить в ios проекте фреймворк как embed фреймворк, указывая где он будет находиться - директория должна быть всегда одна, даже для разных архитектур фреймворка. Далее добавить к проекту build phase, которая будет вызывать у gradle специальную таску. Задача таски - собрать фреймворк и положить его по тому пути, который был указан при добавлении фреймворка в проект. Таким образом нет никаких лишних таргетов. Этот подход описан в текущем туториале от JetBrains "Targeting iOS and Android with Kotlin Multiplatform".
3. Интеграция через CocoaPods используя плагин org.jetbrains.kotlin.native.cocoapods. Для айосников он будет самый удобный. В gradle потребуется добавить специальную конфигурацию плагина (по сути описание pod'а нашего) и плагин автоматически сгенерирует нам podspec. После чего в Podfile от iOS приложения мы просто ссылаемся на наш pod локальный и вся интеграция готова. Под капотом все работает примерно так же как первый и второй случай - создается специальный проект для pod'а, там нет исходного кода но есть embed framework который собирается специальной gradle таской, которая и скомпилирует и перенесет фреймворк по нужному пути. Есть у этого решения пара особенностей - во первых на момент pod install фреймворк должен быть уже скомпилирован, то есть в градле мы должны засинхать проект и запустить gradle task :podspec в нашем mpp проекте. Во вторых - из gradle проекта не видны таски, используемые в xcode build phase (syncFramework в особенности). То есть запустить перекомпиляцию с переносом фреймворка куда-надо из вне xcode нельзя. А еще плагин позволяет подключать iOSные pod'ы в kotlin/native (только те у которых есть objc биндинг).
4. Интеграция через CocoaPods но без плагина org.jetbrains.kotlin.native.cocoapods. Разница в том, что podspec файл один раз пишется и кладется рядом с проектом, а градл таски syncFramework добавляются отдельно к проекту (у нас в IceRock это делает наш mobile-multiplatform плагин) и доступны для запуска просто из IDE или gradle. Это дает больше прозрачности при разработке и полный контроль над самой build phase сборки фреймворка (мы например кеширование на проектах через shell скрипт дополнительное делаем, чтобы не запускать gradle лишний раз при сборках ios проекта - он очень долгий).
Туториал Targeting iOS and Android with Kotlin Multiplatform - https://play.kotlinlang.org/hands-on/Targeting%20iOS%20and%20Android%20with%20Kotlin%20Multiplatform/
Плагин CocoaPods - https://kotlinlang.org/docs/reference/native/cocoapods.html
Плагин mobile-multiplatform - https://github.com/icerockdev/mobile-multiplatform-gradle-plugin
Пример интеграции mobile-multiplatform плагина (пока у него нет ридми) - https://github.com/icerockdev/moko-mvvm/tree/master/sample
#tips
Небольшой список библиотек kotlin multiplatform, покрывающий большинство базовых задач мобильной разработки:
* https://github.com/ktorio/ktor - http клиент, API построено coroutines. Заменяет Retrofit и Alamofire;
* https://github.com/Kotlin/kotlinx.coroutines - асинхронный код в синхронном стиле, вместо калбеков просто помечаем функцию suspend и компилятор добавит калбеки за нас. А сам код будет выглядеть как синхронный. Частично заменяет RxJava/RxSwift ну и калбеки разумеется;
* https://github.com/Kotlin/kotlinx.serialization - сериализация из/в json/cbor/protobuf, работает на аннотациях и кодогенерации. Заменяет gson/jackson/TRON/Codable;
* https://github.com/russhwolf/multiplatform-settings - постоянное key-value хранилище. По сути SharedPreferences/UserDefaults доступные в общем коде;
* https://github.com/cashapp/sqldelight - база данных SQLite доступная в общем коде, с генерацией типобезопасных API. Заменяет Room/Realm/CoreData;
* https://github.com/AAkira/Napier - логирование. Замена Timber/CocoaLumberjack;
* https://github.com/Kodein-Framework/Kodein-DI - внедрение зависимостей (решаются зависимости в рантайме, нет кодогенерации и проверки на этапе компиляции). Замена Dagger/Swinject;
* https://github.com/korlibs/klock - работа с датой и временем, с поддержкой таймзон и форматирования;
* https://github.com/icerockdev/moko-mvvm - компоненты для построения Presentation слоя на базе MVVM. ViewModel'и и LiveData для реактивного обновления UI;
* https://github.com/icerockdev/moko-resources - ресурсы локализации и изображения с доступом из общего кода, и генерацией под обе платформы из одного источника;
* https://github.com/icerockdev/moko-permissions - получение рантайм разрешений из общего кода.
#libs
* https://github.com/ktorio/ktor - http клиент, API построено coroutines. Заменяет Retrofit и Alamofire;
* https://github.com/Kotlin/kotlinx.coroutines - асинхронный код в синхронном стиле, вместо калбеков просто помечаем функцию suspend и компилятор добавит калбеки за нас. А сам код будет выглядеть как синхронный. Частично заменяет RxJava/RxSwift ну и калбеки разумеется;
* https://github.com/Kotlin/kotlinx.serialization - сериализация из/в json/cbor/protobuf, работает на аннотациях и кодогенерации. Заменяет gson/jackson/TRON/Codable;
* https://github.com/russhwolf/multiplatform-settings - постоянное key-value хранилище. По сути SharedPreferences/UserDefaults доступные в общем коде;
* https://github.com/cashapp/sqldelight - база данных SQLite доступная в общем коде, с генерацией типобезопасных API. Заменяет Room/Realm/CoreData;
* https://github.com/AAkira/Napier - логирование. Замена Timber/CocoaLumberjack;
* https://github.com/Kodein-Framework/Kodein-DI - внедрение зависимостей (решаются зависимости в рантайме, нет кодогенерации и проверки на этапе компиляции). Замена Dagger/Swinject;
* https://github.com/korlibs/klock - работа с датой и временем, с поддержкой таймзон и форматирования;
* https://github.com/icerockdev/moko-mvvm - компоненты для построения Presentation слоя на базе MVVM. ViewModel'и и LiveData для реактивного обновления UI;
* https://github.com/icerockdev/moko-resources - ресурсы локализации и изображения с доступом из общего кода, и генерацией под обе платформы из одного источника;
* https://github.com/icerockdev/moko-permissions - получение рантайм разрешений из общего кода.
#libs
GitHub
GitHub - ktorio/ktor: Framework for quickly creating connected applications in Kotlin with minimal effort
Framework for quickly creating connected applications in Kotlin with minimal effort - ktorio/ktor
Сегодня хочется поделиться видео записями выступлений на тему мобильной мультиплатформы с прошедшего Kotlin/Everywhere Minsk.
Интересное:
* Reaktive: реактивное программирование в Kotlin Multiplatform - про перенос Rx в мультиплатформу, с поддержкой смены потоков, разбор от авторов библиотеки (уже было чуть раньше в постах);
* Sliced but whole. A little adventure in multiplatform world - не сильно успешный опыт использования mpp, стоит и такие кейсы знать. Подсвечивает проблемы адаптации людей с градлом, разобран и фронтенд веб с kotlin2js, интероп Firebase ios фреймворка с kotlin/native. Итог от спикера - "не для продакшена". Если рассматривать мобильную разработку - по нашему опыту для продакшена уже полгода как готово :)
* iOS & Kotlin. Путь приложения от начала до публикации в AppStore - взгляд айосника на разработку с kotlin mpp, в кейсе когда айосник единственный разраб на проекте и андроид платформы пока еще нет;
* Kotlin Multiplatform с точки зрения бизнеса - тут понятно из названия. Минимум технической инфы, максимум мнения бизнеса (аутсорс) на технологию и опыт использования.
https://www.youtube.com/playlist?list=PL0SwNXKJbuNmNzTBowoiL7tem0-1gOsmo
#videos
Интересное:
* Reaktive: реактивное программирование в Kotlin Multiplatform - про перенос Rx в мультиплатформу, с поддержкой смены потоков, разбор от авторов библиотеки (уже было чуть раньше в постах);
* Sliced but whole. A little adventure in multiplatform world - не сильно успешный опыт использования mpp, стоит и такие кейсы знать. Подсвечивает проблемы адаптации людей с градлом, разобран и фронтенд веб с kotlin2js, интероп Firebase ios фреймворка с kotlin/native. Итог от спикера - "не для продакшена". Если рассматривать мобильную разработку - по нашему опыту для продакшена уже полгода как готово :)
* iOS & Kotlin. Путь приложения от начала до публикации в AppStore - взгляд айосника на разработку с kotlin mpp, в кейсе когда айосник единственный разраб на проекте и андроид платформы пока еще нет;
* Kotlin Multiplatform с точки зрения бизнеса - тут понятно из названия. Минимум технической инфы, максимум мнения бизнеса (аутсорс) на технологию и опыт использования.
https://www.youtube.com/playlist?list=PL0SwNXKJbuNmNzTBowoiL7tem0-1gOsmo
#videos
Затронем важную часть разработки, которая совсем не видна пользователям, но очень нужна разрабам - логирование. В мобильной мультиплатформе есть небольшой выбор библиотек:
* https://github.com/JakeWharton/timber - стандарт в Android разработке. Мультиплатформенная версия начата, но так и не закончена. Есть форк от Touchlab где доделана и айос версия (https://github.com/touchlab/timber/tree/native), но в bintray нет сборки с актуального котлина (можно просто скачать себе исходники и собрать самому себе в мавен репозиторий);
* https://github.com/AAkira/Napier - библиотека вдохновленная Timber'ом - поддержка обеих мобильных платформ из коробки, api примерно такое же как и у Timber. Так же возможно добавлять свои логгеры (зовутся Antilog). Поддерживает актуальнную версию kotlin;
* https://github.com/korlibs/klogger - мультиплатформенный логгер, без поддержки множества output'ов (как сделано у Timber и Napier) и пока без апдейта до актуального 1.3.50;
* https://github.com/florent37/Multiplatform-Log - самый простейший логгер, так же без поддержки множества output'ов. До актуальной версии kotlin так и не обновлено.
Если подвести краткий вывод - в MPP для логирования брать нужно Napier. Почти тот же Timber, но для всех платформ и не требуется самим пересобирать на новую версию котлина.
#libs
* https://github.com/JakeWharton/timber - стандарт в Android разработке. Мультиплатформенная версия начата, но так и не закончена. Есть форк от Touchlab где доделана и айос версия (https://github.com/touchlab/timber/tree/native), но в bintray нет сборки с актуального котлина (можно просто скачать себе исходники и собрать самому себе в мавен репозиторий);
* https://github.com/AAkira/Napier - библиотека вдохновленная Timber'ом - поддержка обеих мобильных платформ из коробки, api примерно такое же как и у Timber. Так же возможно добавлять свои логгеры (зовутся Antilog). Поддерживает актуальнную версию kotlin;
* https://github.com/korlibs/klogger - мультиплатформенный логгер, без поддержки множества output'ов (как сделано у Timber и Napier) и пока без апдейта до актуального 1.3.50;
* https://github.com/florent37/Multiplatform-Log - самый простейший логгер, так же без поддержки множества output'ов. До актуальной версии kotlin так и не обновлено.
Если подвести краткий вывод - в MPP для логирования брать нужно Napier. Почти тот же Timber, но для всех платформ и не требуется самим пересобирать на новую версию котлина.
#libs
GitHub
GitHub - JakeWharton/timber: A logger with a small, extensible API which provides utility on top of Android's normal Log class.
A logger with a small, extensible API which provides utility on top of Android's normal Log class. - JakeWharton/timber
Обратим внимание на еще один важный для разработки момент - Continuous Integration. Уже нельзя представить современный проект без CI, который как минимум должен автоматизировать деплой билдов, а в идеале - проводить и тестирование и проверку кода на правила разработки.
Что же меняется на CI относительно чисто нативных iOS и Android проектов, если мы начинаем использовать общую библиотеку на Kotlin MultiPlatform?
Ответ - практически ничего. Для android все остается также как было. Для iOS могут потребоваться некоторые изменения. Обратим внимание на них:
1. На раннере собирающем iOS должна быть java для корректного запуска gradle и компиляции kotlin/native;
2. При интеграции общей библиотеки через cocoapods перед вызовом pod install должен быть собран фреймворк (в официальном cocoapods плагине перед pod install нужно вызвать у gradle задачу podspec, а если использовать наш mobile-multiplatform плагин как в moko-template - можно просто вызывать pod install и все сделается само);
3. При интеграции общей библиотеки через билдфазу с отдельным таргетом в самом проекте - билдфаза сама запустит градл и все что нужно сделает, без необходимости делать что-то предварительно;
4. Для запуска тестов на айос пока требуется добавлять отдельную градл таску в конфигурацию общей библиотеки. Таска соберет запускаемый файл тестов и запустит его на симуляторе iOS.
У нас, в IceRock, для CI используется GitLab CI, раннер это mac-mini на котором и xcode и android sdk установлены, сборка android проекта делается полностью средствами градла, а сборка айос полностью средствами Fastlane.
Так же по этой теме есть неплохая статья https://diamantidis.github.io/2019/09/08/continuous-integration-for-kotlin-native-projects-with-gitlab-ci, в которой разобрана вся настройка CI для GitLab под проект с общей библиотекой, включая и запуск тестов и прогон lint. Статья входит в цикл статей про MPP - там есть и про настройку окружения, и про настройку юнит тестов, и про инструменты проверки кода. Есть и проект пример с этим всем https://gitlab.com/diamantidis_io/kmp_template/tree/master
Упомянуто:
https://kotlinlang.org/docs/reference/native/cocoapods.html - официальный gradle плагин cocoapods
https://github.com/icerockdev/mobile-multiplatform-gradle-plugin - gradle плагин для упрощения настройки mobile mpp проектов
https://github.com/icerockdev/moko-template - проект шаблон с использованием mobile-multiplatform плагина (примеры фичей и ридми пока в процессе)
#posts #tips
Что же меняется на CI относительно чисто нативных iOS и Android проектов, если мы начинаем использовать общую библиотеку на Kotlin MultiPlatform?
Ответ - практически ничего. Для android все остается также как было. Для iOS могут потребоваться некоторые изменения. Обратим внимание на них:
1. На раннере собирающем iOS должна быть java для корректного запуска gradle и компиляции kotlin/native;
2. При интеграции общей библиотеки через cocoapods перед вызовом pod install должен быть собран фреймворк (в официальном cocoapods плагине перед pod install нужно вызвать у gradle задачу podspec, а если использовать наш mobile-multiplatform плагин как в moko-template - можно просто вызывать pod install и все сделается само);
3. При интеграции общей библиотеки через билдфазу с отдельным таргетом в самом проекте - билдфаза сама запустит градл и все что нужно сделает, без необходимости делать что-то предварительно;
4. Для запуска тестов на айос пока требуется добавлять отдельную градл таску в конфигурацию общей библиотеки. Таска соберет запускаемый файл тестов и запустит его на симуляторе iOS.
У нас, в IceRock, для CI используется GitLab CI, раннер это mac-mini на котором и xcode и android sdk установлены, сборка android проекта делается полностью средствами градла, а сборка айос полностью средствами Fastlane.
Так же по этой теме есть неплохая статья https://diamantidis.github.io/2019/09/08/continuous-integration-for-kotlin-native-projects-with-gitlab-ci, в которой разобрана вся настройка CI для GitLab под проект с общей библиотекой, включая и запуск тестов и прогон lint. Статья входит в цикл статей про MPP - там есть и про настройку окружения, и про настройку юнит тестов, и про инструменты проверки кода. Есть и проект пример с этим всем https://gitlab.com/diamantidis_io/kmp_template/tree/master
Упомянуто:
https://kotlinlang.org/docs/reference/native/cocoapods.html - официальный gradle плагин cocoapods
https://github.com/icerockdev/mobile-multiplatform-gradle-plugin - gradle плагин для упрощения настройки mobile mpp проектов
https://github.com/icerockdev/moko-template - проект шаблон с использованием mobile-multiplatform плагина (примеры фичей и ридми пока в процессе)
#posts #tips
Ioannis Diamantidis
Continuous Integration for Kotlin Native projects with Gitlab CI
A post to document how to setup a GitLab CI pipeline that will run the code styling and unit test jobs for a Kotlin Native project that contains an iOS app, an Android app and a shared library.
При разговоре о мультиплатформенной разработке iOS разработчики обычно предполагают что это означает отказ от привычных им библиотек. В контексте Kotlin Multiplatform хочется развеять это заблуждение...
* Первый момент (и самый очевидный) - так как UI делается все так же в Swift, то разработчику доступны все нативные библиотеки как через CocoaPods так и Carthage;
* Второе - внутри самой общей библиотеки на Kotlin в ios-specific части тоже можно использовать зависимости из нативного мира - ограничение только в том что библиотека должна иметь objc биндинг (так как Kotlin/Native взаимодействует именно с objc). Вручную это делается через cinterop;
* Третье - для упрощения подключения iOS библиотек к kotlin ios-specific gradle плагин org.jetbrains.kotlin.native.cocoapods позволяет прям в gradle указать список pod'ов которые будут автоматически проброшены в kotlin. И в ios-specific части можно работать с подключенными библиотеками. У плагина есть пара ограничений (нет поддержки SubSpec и собирать библиотеку нужно будет обязательно через Xcode, так как для линковки все данные о подключенных Pod'ах именно у Xcode).
Документация по плагину - https://github.com/JetBrains/kotlin-native/blob/master/COCOAPODS.md
Ручное подключение библиотеки, без плагина - https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#cinterop-support
#tips
* Первый момент (и самый очевидный) - так как UI делается все так же в Swift, то разработчику доступны все нативные библиотеки как через CocoaPods так и Carthage;
* Второе - внутри самой общей библиотеки на Kotlin в ios-specific части тоже можно использовать зависимости из нативного мира - ограничение только в том что библиотека должна иметь objc биндинг (так как Kotlin/Native взаимодействует именно с objc). Вручную это делается через cinterop;
* Третье - для упрощения подключения iOS библиотек к kotlin ios-specific gradle плагин org.jetbrains.kotlin.native.cocoapods позволяет прям в gradle указать список pod'ов которые будут автоматически проброшены в kotlin. И в ios-specific части можно работать с подключенными библиотеками. У плагина есть пара ограничений (нет поддержки SubSpec и собирать библиотеку нужно будет обязательно через Xcode, так как для линковки все данные о подключенных Pod'ах именно у Xcode).
Документация по плагину - https://github.com/JetBrains/kotlin-native/blob/master/COCOAPODS.md
Ручное подключение библиотеки, без плагина - https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#cinterop-support
#tips