欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Kotlin跨平台开发(一)

程序员文章站 2022-07-14 17:03:12
...

Kotlin跨平台开发

  • 今天我们来简单介绍一下使用kotlin进行跨平台开发,使得一处代码,多处运行。

一、简介

首先,我摘取了一些官方文档上的基本介绍。

kotlin语言在一开始设计的时候就有一个明确的目标,那就是能够在所有平台上使用,能够使用kotlin开发任意平台的应用。同时kotlin还有一个重要的目标,就是能够在不同平台间共享代码。

kotlin不仅可以编译为jvm平台的字节码文件,还能够直接编译成二进制文件以及js文件。有了对 JVM、Android、JavaScript、iOS、Linux、Windows、 Mac 甚至像 STM32 这样的嵌入式系统的支持,Kotlin 可以处理现代应用程序的任何组件与所有组件。 这为代码与专业知识的复用带来了宝贵的收益,节省了工作量去完成更具挑战任务,而不是将所有东西都实现两次或多次。

它是如何工作的

总得来说,多平台并不是为所有平台编译全部代码。这个模型有其明显的局限性,我们知道现代应用程序需要访问其所运行平台的独有特性。Kotlin 并不会限制你只使用其中所有 API 的公共子集。 每个组件都可以根据需要与其他组件共享尽可能多的代码, 而通过语言所提供的 expect/actual 机制可以随时访问平台 API。

expect/actual

在一些情况下我们可能需要针对不同的平台编写不同的代码。这时我们需要通过expect关键字在公共代码部分定义需要在不同平台实现的类或者方法,然后在各平台对应的目录下通过actual关键字去实现对应的类或方法。如图中所示,在公共代码部分,writeLogMessage方法通过expect关键字定义。

Kotlin跨平台开发(一)

然后我们需要在不同的平台中去实现该方法如js平台的实现:

Kotlin跨平台开发(一)

jvm平台的实现:

Kotlin跨平台开发(一)

多平台库依赖其他多平台库

二、项目搭建

(一)项目创建

这里建议使用最新的idea,虽然理论上项目使用gradle构建,用Android studio应该也是没问题的,但是idea自带项目骨架,还是方便不少。

1.使用idea新建项目,在kotlin项目中选择Multiplatform Library

Kotlin跨平台开发(一)

Kotlin跨平台开发(一)

Kotlin跨平台开发(一)

小技巧:

  • 默认的项目构建依赖的gradle版本本地没有,需要下载,此时可终止任务,修改本地存在的较新版本的gradle。
  • 项目默认会构建macos平台,会下载相关依赖库,如果不需要macos平台可以终止任务后在build.gradle中移除macos相关配置

(二)项目结构

创建项目后会自动生成以下目录

Kotlin跨平台开发(一)

commonMain目录是公共代码所在的目录

目录 介绍
commonMain 公共代码
commonTest 公共测试代码
jsMain Js平台代码
jsTest Js平台测试代码
jvmMain jvm平台代码(Android)
jvmTest jvm平台测试代码
macosMain macos平台代码
macosTest macos平台测试代码
iosMain ios平台代码
iosTest ios平台测试代码

注:默认没有iOS目录,如果需要iOS平台需自行手动创建

commonMain内的结构和普通项目类似

Kotlin跨平台开发(一)

(三)项目build.gradle

默认文件:

plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.3.61'//配置kotlin多平台插件和版本
}
repositories {
    mavenCentral()//配置maven*仓库
}
group 'com.example'//定义包所在组
version '0.0.1'//版本

apply plugin: 'maven-publish'//引用maven上传插件

kotlin {//用于配置需要构建的平台信息
    jvm()//构建jvm平台,输出jar包
    js {//构建js平台,输出js module
        browser {//构建适用于浏览器环境的js模块
        }
        nodejs {//构建适用于node环境的js模块
        }
        //由于nodejs和browser环境提供的API不同,所以需要区分。
    }
    // For ARM, should be changed to iosArm32 or iosArm64
    // For Linux, should be changed to e.g. linuxX64
    // For MacOS, should be changed to e.g. macosX64
    // For Windows, should be changed to e.g. mingwX64
    macosX64("macos")//构建macos平台,输出framework
    sourceSets {//源码设置
        commonMain {//公共代码目录
            dependencies {//公共代码需要的依赖
                implementation kotlin('stdlib-common')
            }
        }
        commonTest {//公共代码测试
            dependencies {
                implementation kotlin('test-common')
                implementation kotlin('test-annotations-common')
            }
        }
        jvmMain {//jvm代码目录
            dependencies {
                implementation kotlin('stdlib-jdk8')
            }
        }
        jvmTest {
            dependencies {
                implementation kotlin('test')
                implementation kotlin('test-junit')
            }
        }
        jsMain {
            dependencies {
                implementation kotlin('stdlib-js')
            }
        }
        jsTest {
            dependencies {
                implementation kotlin('test-js')
            }
        }
        macosMain {
        }
        macosTest {
        }
    }
}

根据需求修改后的文件

buildscript {//对构建脚本的配置
    repositories {//仓库配置
        mavenLocal()//使用本地maven仓库
        mavenCentral()
        maven {//kotlinx需要的仓库
            url 'https://dl.bintray.com/kotlin/kotlinx/'
        }
        maven {//阿里国内镜像仓库
            url 'http://maven.aliyun.com/nexus/content/groups/public/'
        }
        maven {
            url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
        }
        maven { url 'https://plugins.gradle.org/m2/' }
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
    }
}
plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.3.61'//配置kotlin多平台插件和版本
}
apply plugin: 'kotlinx-serialization'//引用跨平台序列化插件

repositories {//项目依赖使用的仓库
    mavenLocal()
    mavenCentral()
    maven {//配置私有maven仓库
        url QT_RELEASE_URL
        credentials {//配置私有maven仓库用户名密码
            username QT_NAME
            password QT_PASSWORD
        }
        content {//配置该maven仓库仅在查询其group符合"im.qingtui.*"的模块时使用
            // this repository *only* contains artifacts with group "my.company"
            includeGroupByRegex "im\\.qingtui.*"
        }
        mavenContent {//配置该maven仓库仅在查询release模块时使用
            releasesOnly()
        }
    }

    maven {
        url QT_SNAPSHOT_URL
        credentials {
            username QT_NAME
            password QT_PASSWORD
        }
        content {
            // this repository *only* contains artifacts with group "my.company"
            includeGroupByRegex "im\\.qingtui.*"
        }
        mavenContent {//配置该maven仓库仅在查询snapshot模块时使用
            snapshotsOnly()
        }
    }
    maven {
        url 'https://dl.bintray.com/kotlin/kotlinx/'
    }
}
group 'im.qingtui.sns'
version '0.0.1-SNAPSHOT'

kotlin {
    jvm()
    js {
        browser {
        }
        nodejs {
        }
    }
    iosArm64("ios") {//构建iOS库
        binaries {
            framework()
        }
    }
    sourceSets {
        commonMain {...}
        commonTest {...}
        jvmMain {...}
        jvmTest {...}
        jsMain {...}
        jsTest {...}
        iosMain {...}
    }
}


apply plugin: 'maven-publish'//引用maven上传插件,如果仅打包到本地,可以不使用
publishing {//配置maven上传时使用的信息
    publications {
        maven(MavenPublication) {
            //指定group/artifact/version信息,可以不填。默认使用项目group/name/version作为groupId/artifactId/version
            groupId project.group
            artifactId project.name
            version project.version
        }
    }
    repositories {
        maven {
            def VERSION = project.version.toString()
            //指定要上传的maven私服仓库地址
            url = VERSION.contains("SNAPSHOT") ? QT_SNAPSHOT_URL : QT_RELEASE_URL
            //认证用户和密码
            credentials {
                username QT_NAME
                password QT_PASSWORD
            }
        }
    }
}

提示:

Kotlin版本、Gradle版本、Xcode版本、系统版本都存在依赖关系,

所依赖的第三方库也存在依赖关系

建议均使用最新版本

可以通过maven仓库搜索查看最新版本

四、打包发布

(一)执行打包任务

打开右侧gradle面板

执行assemble任务

Kotlin跨平台开发(一)

然后在项目目录下可以看到build目录

Kotlin跨平台开发(一)

(二)本地依赖包

在build目录我们可以找到各个平台需要的库文件

Kotlin跨平台开发(一)

在bin目录下可以找到iOS平台需要的framework文件。js目录下是js平台可以使用module。jvm以及Android平台可以直接使用libs目录下的xxx-jvm-version.jar文件

(三)上传maven仓库

我们也可以使用maven-publish插件将库上传到maven仓库中。构建脚本会分个平台生成多个平台的jar包,然后上传至maven。

apply plugin: 'maven-publish'

Kotlin跨平台开发(一)

在build.gralde文件中引用maven-publish插件,并配置后,在右侧gradle的面板中即可看到对应的publish任务

Kotlin跨平台开发(一)

1.本地maven仓库上传

执行publishToMavenLocal任务即可将各平台库打包成jar并发布到本地的maven仓库中。我们也可以选择性的发布某一个平台的jar到本地maven仓库中。

2.远程maven上传

执行publish任务即可将各平台库打包并发布到本地的maven仓库中。

Kotlin跨平台开发(一)

(三)npm仓库上传

对于npm仓库的上传,可直接修改build/js目录下pacakage.json的相关配置,然后执行npm publish命令进行上传

五、库的使用

kotlin跨平台技术实际上已经为我们生成了各平台对应的库,在库的使用上与以往没有什么差别。Android和jvm平台可以使用本地或maven仓库中jvm平台的jar包iOS平台可以使用build目录下生成的framework库文件js平台可以将build/js目录作为module使用,或将module上传至npm

下一章我们将继续介绍在多个平台能同时使用的网络库、序列化库,使网络请求相关的代码只需要一份,即可在多个平台运行。