Kotlin Multiplatform
2.63K subscribers
84 photos
3 videos
407 links
Русскоязычный канал новостей о Kotlin Multiplatform
Download Telegram
Пока нет горячих новостей продолжим обзор доступных библиотек. Не так давно появился плагин, который автоматически генерирует для корутин методы которые будут доступны на стороне iOS. Проблема с корутинами на айос не только в отсутствии многопоточности, но и в том что все suspend функции недоступны для вызова из swift (такой вид функций в swift не существует). А плагин при выставлении специальной аннотации автоматически сгенерирует код функции с калбеком, которая внутри уже вызывает suspend функцию. Тем кто хочет иметь доступ с натива до suspend функций - must have.
https://github.com/feilfeilundfeil/kotlin-native-suspend-function-callback

#libs
Сегодня поделюсь недавно опубликованной презентацией доклада о kotlin multiplatform задевающей и сравнение с кроссплатформенными решениями, и создание приложения с стандартной функциональностью мобилок - работа с сетью, хранение данных локально, вывод данных пользователю. Основная ценность именно в наглядном и доступном примере - не "hello world", а с обычным функционалом мобильных приложений. В комплекте и сравнение техстека нативок и мультиплатформенной разработки, и сравнение языков, и отзывы айос разработчиков, и немного рекомендаций. Для тех кто с темой знакомится - рекомендую. Для тех кто уже разрабатывает на мультиплатформе - скорей всего нового ничего не будет (если только работа с sqldelight в новинку, ну и отзывы айосников).
https://speakerdeck.com/cmota/the-hitchhikers-guide-through-kotlin-multiplatform-extended
демо проект тут - https://github.com/cmota/droidconLX

#slides
Обратим внимание на работу с датой и временем - в 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
Сегодня заденем тему отладки, а именно - отладки библиотеки написанной на 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
Немного про подключение 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
Небольшой список библиотек 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
Channel photo removed
Channel photo updated
Сегодня хочется поделиться видео записями выступлений на тему мобильной мультиплатформы с прошедшего 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
Затронем важную часть разработки, которая совсем не видна пользователям, но очень нужна разрабам - логирование. В мобильной мультиплатформе есть небольшой выбор библиотек:
* 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
Обратим внимание на еще один важный для разработки момент - 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
При разговоре о мультиплатформенной разработке 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
Forwarded from Nikolay
Небольшое дополнение - можно взаимодействовать и с библиотеками написанными на Си, а также возможно работать и в другую сторону, экспортируя Котлин в виде Objective-C или C деклараций.
Наконец-то опубликованы видео с прошедшего DroidCon New York, на котором было очень много внимания уделено именно Kotlin Multiplatform в мобильной разработке. Что есть:
* Native Concurrency and Coroutines - от автора библиотеки CoroutineWorker , которая позволяет выполнять suspend функции на отдельных потоках - как появилась библиотека и как используется в Autodesk;
* Multiplatform Library Development - от автора библиотеки multiplatform-settings - про разработку mpp библиотеки, про проектирование апи под обе платформы, про состояние kotlin mpp на данный момент;
* Lessons Learned from Using Kotlin Multiplatform internally - опыт погружения андроид и айос специалистов в мультиплатформу, какие шишки набивали, какие выводы сделали, фидбек айосников;
* Effective Multiplatform Architecture - очень классная презентация с полезными аргументами как продать мпп бизнесу, так и для технарей с полезными идеями как вводить мультиплатформу в существующий проект;
* Multiplatform Functional Architecture - про архитектуру MVU (Model-View-Update) на мультиплатформе. Библиотека oolong поможет строить такую архитектуру. Для любителей Redux;
* SwiftUI meets Kotlin Multiplatform! - небольшой доклад про то как дружили общую библиотеку и SwiftUI. Для этого предложено и ViewModel'и унести на сторону нативного android, ios кода;
* Using Kotlin/JS and Kotlin/Native on Android - доклад от Jake Wharton о том как на андроиде он дружил обычный котлин, нативный котлин и kotlin js в одном приложении;
* Building apps using Kotlin Native - расказ про разработку общей библиотеки, для новичков в теме. Даже задета тема про Worker'ы для многопоточности на Native.

#videos
Сегодня поделюсь статьей, которую возможно уже видели в сети, но она имеет очень интересную информацию. Статья про разработку библиотеки kissme - не про поцелуи, а про хранение данных в keychain. Помимо просто истории о разработке multiplatform библиотеки и столкновением с некоторыми ограничениями, тут есть то что не часто встретишь - линковка objective-c библиотеки в kotlin код. У ребят как раз был кейс, что не смогли через kotlin ios-specific код сделать нужную функциональность и поэтому решили сделать дополнительно objective-c библиотеку, которую прилинковали к котлину через cinterop и в итоге вызывали из котлина функции своей библиотеки.
Kissme: Kotlin Secure Storage Multiplatform library. The Code Story.

#posts #libs
Сегодня у нас пост новостей от JetBrains.
Kotlin/Native в следующем релизе получит:
* поддержка Xcode 11
* новый LLVM
* новые API iOS, macOS
* поддержка watchOS и tvOS.
Подробнее тут - https://github.com/JetBrains/kotlin-native/pull/3391
Попробовать можно будет уже скоро - EAP планируется в ближайшие недели.

Так же вы можете задать вопросы про новый релиз напрямую авторам в нашем чатике - нажимайте Discuss и обращайтесь - Николай Иготти уже там (новость как раз от него).

#news
Ioannis Diamantidis продолжает свою серию статей о Kotlin/Native. Новая статья From Kotlin to Native: Or how Kotlin concepts are mapped to the Apple framework разбирает некоторые особенности получаемого из Kotlin кода iOS фреймворка - как Kotlin код выглядит из ObjectiveC и Swift.
Это не полный список особенностей на стыке Kotlin и ObjC, но знать их очень полезно. Так же еще особенности можно подсмотреть в нашей летней статье - Опыт работы с Kotlin Multiplatform за 10 месяцев. Краткий список особенностей kotlin на стыке с ios доступен в презентации.
Так же в октябре на AppsConf мы отметим еще несколько новых особенностей по актуальной версии Kotlin.

#posts #slides
Можно ли работать с базой данных из common кода под ios и android? Ответ - конечно можно :) И есть несколько путей:
1. Метод "в лоб" - делаем interface реализация которого будет проброшена с нативной стороны и на android и ios делаем отдельные реализации БД так, как привыкли разработчики;
2. Делаем expect/actual классы, чтобы уже внутри котлина реализовать всю работу с БД, используя нативные средства Android и iOS в actual реализациях;
3. Используем библиотеку SQLiter которая позволяет в common коде работать с sqlite БД напрямую, без каких либо оберток;
4. Используем библиотеку SQLDelight от известных square (которые успели переименоваться в cashapp). Данная библиотека идет в паре с gradle plugin'ом который из специального файла, в котором описана схема базы данных и запросы, которые планируется выполнять, генерирует сущности и методы для выполнения запросов. И все это доступно из common кода для обеих мобильных платформ, а так же уже проверено на Android годами ранее.

Рекомендуемый на данный момент способ это конечно SQLDelight. Для знакомства с ним можно воспользоваться:
* Презентацией SELECT * SQLDelight JOIN Multiplatform в которой разобраны преимущества библиотеки;
* Статьей SQLDelight 1.x Quick Start Guide for Android с пошаговой инструкцией и даже примером юниттестирования;
* Статьей Kotlin Multiplatform. Very beginner’s guide (part 3) Database с пошаговым примером реализации БД, но статья со времен kotlin 1.3.31, так что возможны некоторые нестыковки, особенно по версиям библиотек используемых - с 1.3.50 на айос не сойдутся они, нужно более новые;
* Проектом Droidcon Lisbon - здесь в app есть common source set и используется SQLDelight с версией kotlin 1.3.41;
* Проектом Newsout тоже на версии kotlin 1.3.41.

А еще SQLDelight поддерживает Flow для оповещения о изменениях, но на iOS там есть проблемы, требующие обхода.

#libs #slides #projects
Тем кто интересуется темой тестирования кода будет полезна статья Shared Library in Kotlin Multiplatform в которой разобрано по шагам создание общей библиотеки и добавление к ней простых тестов.
В паре с статьей идет и проект-пример, в котором можно наглядно посмотреть и тесты и демо приложение, работающее с сетью (ktor-client, kotlinx.serialization, coroutines - стандартный mpp набор).
Еще примеры тестов можно посмотреть в проекте-примере от russwolf (автор multiplatform-settings) и в еще одном проекте примере.

#posts #samples #tests
Badoo продолжает радовать контентом по Kotlin Multiplatform. В этот раз подготовили хоршую подробную статью по настройке автосборки для мультиплатформенной библиотеки - Continuous delivery для вашей Kotlin Multiplatform библиотеки. Стоит ознакомиться со статьей даже тем, кто не собирается настраивать CI/CD, так как помимо конфигурации для автоматической сборки и выгрузки в maven репозиторий через Travis CI всех таргетов библиотеки, там описано и строение публикуемых данных - особенно интересно про Gradle Metadata, что так активно используется Kotlin Multiplatform проектами. Всем бы авторам MPP библиотек настроить автоматизацию на github по примеру ребят, чтобы апдейты к библиотекам выходили как можно быстрее, после релиза новой версии котлина.

#posts #libs