Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CodeFest 2019. Илья Матвеев (JetBrains) — Мультиплатформенные проекты в Kotlin 1.3

CodeFest 2019. Илья Матвеев (JetBrains) — Мультиплатформенные проекты в Kotlin 1.3

Многие знают Котлин в первую очередь как язык для разработки под Android и JVM. Однако это не единственные поддерживаемые платформы, и Котлин компилируется также в JavaScript и нативный код для различных архитектур. Естественным результатом такого разнообразия компиляторов стало появление проектов, в которых переиспользуется код под разные платформы.

Начиная с версии 1.2 экспериментальная поддержка таких мультиплатформенных проектов была добавлена в язык на уровне синтаксиса и со стороны тулинга. На практике это означает, что у программиста на Котлине появилась возможность использовать один и тот же код на разных платформах, при этом не теряя доступа к платформенно-специфичным API. Эта фича носит статус экспериментальной, а, значит, это одно из тех мест в языке, где изменения происходят чаще всего. Релиз 1.3 не стал исключением и поддержка мультиплатформенных проектов в нем была заметно переработана.

Этот доклад посвящён как самой по себе концепции мультиплатформенных проектов в Котлине, так и тем изменениям, которые появились в ней начиная с версии 1.3. Поэтому он будет интересен и тем, кто еще не знаком с этой фичей, и тем, кто уже успел попробовать ее в Kotlin 1.2.
В докладе поговорим:

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

CodeFest

April 06, 2019
Tweet

More Decks by CodeFest

Other Decks in Programming

Transcript

  1. О чём будем говорить? • Лирика: общие концепции MPP* •

    Теория: как это выглядит в языке и тулинге • Практика: приложение iOS + Android 2 *MPP - мультиплатформенное программирование
  2. Что хотим? • Переиспользовать код на разных платформах • Иметь

    доступ к платформенно-специфичным API • Пользоваться поддержкой со стороны IDE 8
  3. Как это работает Android код Разделяемый код iOS код Платформенный

    код • UI • Платформенные API Разделяемый код • Высокоуровневая логика • Работа с сетью/БД 10
  4. Expect/actual expect class Logger { fun log(message: String) } import

    android.util.Log actual class Logger { fun log(message: String) { Log.i("Tag", message) } } import platform.Foundation.* actual class Logger() { fun log(message: String) { NSLog(message) } } 15
  5. Expect/actual expect class Logger { constructor(tag: String) // ... }

    expect fun withLogger(action: Logger.() -> Unit) expect fun Logger.logError(exception: Throwable) 16 Expect-класс может иметь конструктор Можно объявлять expect-функции
  6. Expect/actual package kotlin.collections expect class ArrayList<E> : MutableList<E>, RandomAccess {

    /* ... */ } package kotlin.collections actual typealias ArrayList<E> = java.util.ArrayList<E> 18
  7. Expect/actual package kotlin.test expect annotation class Test package kotlin.test actual

    typealias Test = org.junit.Test 21 package kotlin.test actual typealias Test = org.testng.annotations.Test
  8. Мультиплатформа и Gradle (1.2) 24 :common :android :ios Root project

    apply plugin: 'kotlin-platform-common' dependencies { compile 'org.jetbrains.kotlin:kotlin-stdlib-common' } apply plugin: 'kotlin-platform-android' dependencies { expectBy project( ':common') compile 'org.jetbrains.kotlin:kotlin-stdlib' }
  9. Мультиплатформа и Gradle (1.2) 25 :common :android :ios Root project

    apply plugin: 'kotlin-platform-common' dependencies { compile 'org.jetbrains.kotlin:kotlin-stdlib-common' } apply plugin: 'kotlin-platform-android' dependencies { expectBy project(':common') compile 'org.jetbrains.kotlin:kotlin-stdlib' } Подключаем плагины
  10. Мультиплатформа и Gradle (1.2) 26 :common :android :ios Root project

    apply plugin: 'kotlin-platform-common' dependencies { compile 'org.jetbrains.kotlin:kotlin-stdlib-common' } apply plugin: 'kotlin-platform-android' dependencies { expectBy project(':common') compile 'org.jetbrains.kotlin:kotlin-stdlib' } Добавляем внешние зависимости
  11. Мультиплатформа и Gradle (1.2) 27 :common :android :ios Root project

    apply plugin: 'kotlin-platform-common' dependencies { compile 'org.jetbrains.kotlin:kotlin-stdlib-common' } apply plugin: 'kotlin-platform-android' dependencies { expectBy project( ':common') compile 'org.jetbrains.kotlin:kotlin-stdlib' } Связываем платформенный и common код
  12. Проблемы модели 1.2 34 org.example:my-library:1.0 org.example:my-application:1.0 Depends on Root project

    :common :android :ios :macos :windows :linux Root project :common :android :ios :macos :windows :linux
  13. Проблемы модели 1.2 36 org.example:my-library:1.0 dependencies { compile 'org.example:my-library-common' }

    dependencies { compile 'org.example:my-library-ios' } dependencies { compile 'org.example:my-library-linux' } ...
  14. Проблемы модели 1.2 1. Число модулей растет с числом платформ

    2. Зависимости настраиваются вручную 37
  15. Мультиплатформа и Gradle в 1.3 commonMain commonTest jvmTest jvmMain iosMain

    iosTest jvm main test ios main test 41 Source sets Targets Compilations
  16. Мультиплатформа и Gradle в 1.3 commonMain commonTest jvmTest jvmMain iosMain

    iosTest jvm main test ios main test JVM classes iOS binary 42 Source sets Targets Compilations
  17. Мультиплатформа и Gradle в 1.3 commonMain androidMain androidRelease android release

    debug 43 Source sets Targets ... ... androidDebug Release classes Debug classes
  18. Мультиплатформа и Gradle в 1.3 apply plugin: "kotlin-multiplatform" kotlin {

    sourceSets.commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common" } } android { /* Android-specific configuration */ } iosArm64 { /* iOS-specific configuration */ } } 44
  19. Мультиплатформа и Gradle в 1.3 apply plugin: "kotlin-multiplatform" kotlin {

    sourceSets.commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common" } } android { /* Android-specific configuration */ } iosArm64 { /* iOS-specific configuration */ } } 45 Подключаем плагин
  20. Мультиплатформа и Gradle в 1.3 apply plugin: "kotlin-multiplatform" kotlin {

    sourceSets.commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common" } } android { /* Android-specific configuration */ } iosArm64 { /* iOS-specific configuration */ } } 46 Конфигурируем source set-ы
  21. Мультиплатформа и Gradle в 1.3 apply plugin: "kotlin-multiplatform" kotlin {

    sourceSets.commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common" } } android { /* Android-specific configuration */ } iosArm64 { /* iOS-specific configuration */ } } 47 Конфигурируем source set-ы Настраиваем зависимости
  22. Мультиплатформа и Gradle в 1.3 apply plugin: "kotlin-multiplatform" kotlin {

    sourceSets.commonMain { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-common" } } android { /* Android-specific configuration */ } iosArm64 { /* iOS-specific configuration */ } } 48 Конфигурируем таргеты
  23. Проблемы модели 1.2 1. Число модулей растет с числом платформ

    2. Зависимости настраиваются вручную 49
  24. Управление зависимостями 50 commonMain.dependencies { implementation "org.example:my-library-common" } iosMain.dependencies {

    implementation "org.example:my-library-ios" } androidMain.dependencies { implementation "org.example:my-library-android" } Платформенные артефакты
  25. Variant-aware dependency management org.example: my-library:1.0 54 my-library-ios.klib platform = ios_arm64

    ... my-library-android.aar platform = android ... my-library-jvm.jar platform = jvm ...
  26. Variant-aware dependency management org.example: my-library:1.0 55 my-library-ios.klib platform = ios_arm64

    ... my-library-android.aar platform = android ... my-library-jvm.jar platform = jvm ... Consumer platform = android ...
  27. Variant-aware dependency management org.example: my-library:1.0 56 my-library-ios.klib platform = ios_arm64

    ... my-library-android.aar platform = android ... my-library-jvm.jar platform = jvm ... Consumer platform = android ...
  28. Gradle metadata 61 "variants": [ { "name": "android-releaseApiElements", "attributes": {

    "org.gradle.usage": "java-api", "org.jetbrains.kotlin.platform.type": "androidJvm", ... }, "available-at": { "url": "../../my-library-android/1.0/my-library-android-1.0.module", ... } }, ... ] Имя варианта Атрибуты Адрес артефакта
  29. Проблемы модели 1.2 1. Число модулей растет с числом платформ

    2. Зависимости настраиваются вручную 63
  30. Gradle metadata Gradle metadata имеет экспериментальный статус → Нет совместимости

    между разными версиями* 64 *До версии 5.3: https://docs.gradle.org/5.3/release-notes.html
  31. Gradle metadata 66 org.example:my-library:1.0 org.example:my-library:1.0 org.example:my-library:1.0 org.example: my-application:1.0 Gradle: 5.0

    Metadata: 0.4 Gradle: 4.7 Metadata: 0.3 Depends on FAILURE: Build failed with an exception. ... > Could not parse module metadata my-library-1.0.module > Unsupported format version '0.4' specified in module metadata. This version of Gradle supports format version 0.3 only.
  32. Gradle metadata 1. Не критично для мультиплатформенных проектов • Метаданные

    можно вырубить 2. Критично для библиотек, доступных вне MPP 68
  33. Gradle metadata 1. Не критично для мультиплатформенных проектов • Метаданные

    можно вырубить 2. Критично для библиотек, доступных вне MPP • JVM/JS публикуем без метаданных • Native - с метаданными 69
  34. Библиотека SharedCode 77 // Call iOS platform API. actual fun

    platformName() = with(UIDevice.currentDevice) { "$systemName $systemVersion" }
  35. iOS-приложение 90 import SharedCode // ... @IBOutlet weak var label:

    UILabel! // … label.text = CommonKt.screenMessage()
  36. Обратная связь • Kotlin Slack: kotlinlang.slack.com (канал #multiplatform) • Баг-трекер:

    youtrack.jetbrains.com/issues/KT • GitHub: ◦ github.com/JetBrains/kotlin ◦ github.com/JetBrains/kotlin-native 93