Connect with us

Программирование

Мультиплатформенный Kotlin: создаем проект

Мы большие поклонники языка программирования Kotlin. С того самого момента, как Google объявил, что будет официально поддерживать его, мы решили потратить некоторое время на его изучение и освоение.

Опубликовано

/

     
     

Мы влюбились в него с самого начала — от выразительности системы типов до поддержки функций более высокого порядка. Было здорово заново открыть для себя разработку для Android с помощью такого мощного инструмента. Нам нравится думать, что это было только начало. Мы внимательно следим за последними обновлениями от команды JetBrains. Наибольший интерес вызывает команда, которая делает мультиплатформенный Kotlin. Это означает, что помимо возможности использования Kotlin в приложениях для Android, теперь мы можем писать приложения для iOS, бэкэнд и веб-интерфейс на нашем любимом языке!

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

Бесплатный курс “Разработка Android-приложений на Kotlin” от Google

Модель

Мультиплатформенные проекты Kotlin обычно делятся на несколько модулей. Будет один для каждой платформы, где мы хотим выпустить приложение — в данном случае один для iOS и один для Android. Мы создаем еще один модуль для повторного использования кода на обеих платформах, shared или common модуль. Многоплатформенная сборка работает через создание артефакта общего модуля для каждой целевой целевой платформы — чтобы впоследствии использовать его на ней.

Мультиплатформенный Kotlin

Это означает, что Kotlin будет генерировать для конечных проектов оба файла, и файл jar, и файл фреймворка, из одного и того же кода. Пунктир на рисунке выше показывает, чего мы хотим достичь. Несмотря на то, что Kotlin Multiplatform предназначен и для использования в Backend и Web, мы не будем их задействовать в рамках нашего небольшого эксперимента.

Чтобы настроить многоплатформенный проект и все его зависимости, нам нужно сначала создать новый файл Gradle для создания shared модуля.

shared/build.gradle

kotlin {
    targets {
        fromPreset(presets.jvm, "jvm")

        fromPreset(presets.iosX64, "ios_x86_64")
        fromPreset(presets.iosArm64, "ios_arm64")
        configure([ios_x86_64, ios_arm64]) {
            compilations.main.outputKinds("FRAMEWORK")
        }
    }
    
    sourceSets {
        commonMain {
            dependencies {
                implementation "org.jetbrains.kotlin:kotlin-stdlib"
            }
        }
        jvmMain {
            dependencies {
                implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
            }
        }
        iosMain {
            dependencies {
            }
        }
        configure([ios_x86_64Main, ios_arm64Main]) {
            dependsOn iosMain
        }
    }
}

configurations {
    compileClasspath
}

Мы можем видеть множество iOS-настроек, которые мы рассмотрим позже. Затем мы определяем конфигурацию Android-проекта и говорим Gradle добавить зависимость к общему модулю.

androidApp/build.gradle.kts
android {
    buildToolsVersion = "28.0.3"
    compileSdkVersion(28)
    defaultConfig {
        minSdkVersion(21)
        targetSdkVersion(28)
        multiDexEnabled = true
        versionCode = 1
        testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
        }
    }

    sourceSets {
        getByName("main").java.srcDirs("src/main/kotlin")
    }
}

dependencies {
    implementation("com.android.support.constraint:constraint-layout:1.1.3")
    implementation("com.android.support.constraint:constraint-layout:1.1.3")
    implementation("com.android.support:appcompat-v7:28.0.0")
    implementation("com.android.support:recyclerview-v7:28.0.0")
    implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
    implementation(project(":shared"))
}

Наконец, мы должны настроить iOS-проект. Это самый сложный шаг в этом процессе. Ведь iOS работает со своим собственным набором инструментов для сборки. Хитрость заключается в том, чтобы создать новую задачу Gradle для создания артефакта фреймворка. Важно помнить, что нам нужно создать артефакт для разных архитектур, x86_64 для симулятора и arm64 для реальных устройств.

shared/build.gradle

task packForXCode(type: Sync) {
    final File frameworkDir = new File(buildDir, "xcode-frameworks")

    final String configuration = project.findProperty("CONFIGURATION")?.toUpperCase() ?: "DEBUG"
    final String arch = project.findProperty("ARCHS") ?: "x86_64"

    dependsOn kotlin.targets."ios_${arch}".compilations.main.linkTaskName("FRAMEWORK", configuration)

    from { kotlin.targets."ios_${arch}".compilations.main.getBinary("FRAMEWORK", configuration).parentFile }
    into frameworkDir
}

tasks.build.dependsOn packForXCode

Теперь мы можем настроить сборку XCode для компилирования общего модуля через новую задачу Gradle, и включить сгенерированный фреймворк в проект.

cd ${SRCROOT}/..
./gradlew :shared:packForXCode \
  -PCONFIGURATION=${CONFIGURATION} \
  -PARCHS=${ARCHS}

Выполняем основные проверки

Когда проект запущен для обеих платформ, мы хотим инвестировать в качественную разработку. Мы настроим SwiftLint в проекте iOS, добавив Podfile с зависимостью:

platform :ios, "11.4"

target "Multiplatform app" do
  use_frameworks!
  pod "SwiftLint"
end

Для Android мы использовали наши обычные инструменты — ktlint и detekt. Добавить их легко, так как в Android-проекте  они уже используются.

shared/build.gradle
apply plugin: "io.gitlab.arturbosch.detekt"
apply plugin: "org.jlleitschuh.gradle.ktlint"

ktlint {
    version = "0.30.0"
    verbose = true
    android = false
    outputToConsole = true
    reporters = [ReporterType.PLAIN, ReporterType.CHECKSTYLE]
    filter {
        exclude("**/generated/**")
        include("**/kotlin/**")
    }
}

detekt {
    toolVersion = "1.0.0-RC14"
    input = files("src/main/kotlin")
    filters = ".*/resources/.*,.*/build/.*"
}

check.dependsOn ktlintCheck
check.dependsOn "detekt"

CI

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

Для Android мы запускаем все юнит-тесты и проверки lint. Для iOS мы постарались сделать то же самое, но мы все еще сталкиваемся с некоторыми проблемами, пытаясь сформировать стек, поддерживающий современные версии Gradle и XCode.

Podlodka #50: Kotlin и Swift

Итого

Мы по-прежнему усердно работаем над решением некоторых проблем. Это исправление нашего CI для iOS -сборок или максимально эффективное использование нашей архитектуры для повторного использования как можно большего кода. Оставляйте комментарии и следите за публикациями.

Источник

Приложение с прогнозом погоды на Kotlin, Retrofit и RxJava2

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.

Наши партнеры:

LEGALBET

Мобильные приложения для ставок на спорт
Хорошие новости

Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: