赞
踩
首先,我摘取了一些官方文档上的基本介绍。
kotlin语言在一开始设计的时候就有一个明确的目标,那就是能够在所有平台上使用,能够使用kotlin开发任意平台的应用。同时kotlin还有一个重要的目标,就是能够在不同平台间共享代码。
kotlin不仅可以编译为jvm平台的字节码文件,还能够直接编译成二进制文件以及js文件。有了对 JVM、Android、JavaScript、iOS、Linux、Windows、 Mac 甚至像 STM32 这样的嵌入式系统的支持,Kotlin 可以处理现代应用程序的任何组件与所有组件。 这为代码与专业知识的复用带来了宝贵的收益,节省了工作量去完成更具挑战任务,而不是将所有东西都实现两次或多次。
总得来说,多平台并不是为所有平台编译全部代码。这个模型有其明显的局限性,我们知道现代应用程序需要访问其所运行平台的独有特性。Kotlin 并不会限制你只使用其中所有 API 的公共子集。 每个组件都可以根据需要与其他组件共享尽可能多的代码, 而通过语言所提供的 expect/actual 机制可以随时访问平台 API。
在一些情况下我们可能需要针对不同的平台编写不同的代码。这时我们需要通过expect关键字在公共代码部分定义需要在不同平台实现的类或者方法,然后在各平台对应的目录下通过actual关键字去实现对应的类或方法。如图中所示,在公共代码部分,writeLogMessage方法通过expect关键字定义。
然后我们需要在不同的平台中去实现该方法如js平台的实现:
jvm平台的实现:
这里建议使用最新的idea,虽然理论上项目使用gradle构建,用Android studio应该也是没问题的,但是idea自带项目骨架,还是方便不少。
创建项目后会自动生成以下目录
commonMain目录是公共代码所在的目录
目录 | 介绍 |
---|---|
commonMain | 公共代码 |
commonTest | 公共测试代码 |
jsMain | Js平台代码 |
jsTest | Js平台测试代码 |
jvmMain | jvm平台代码(Android) |
jvmTest | jvm平台测试代码 |
macosMain | macos平台代码 |
macosTest | macos平台测试代码 |
iosMain | ios平台代码 |
iosTest | ios平台测试代码 |
注:默认没有iOS目录,如果需要iOS平台需自行手动创建
commonMain内的结构和普通项目类似
默认文件:
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任务
然后在项目目录下可以看到build目录
在build目录我们可以找到各个平台需要的库文件
在bin目录下可以找到iOS平台需要的framework文件。js目录下是js平台可以使用module。jvm以及Android平台可以直接使用libs目录下的xxx-jvm-version.jar文件
我们也可以使用maven-publish插件将库上传到maven仓库中。构建脚本会分个平台生成多个平台的jar包,然后上传至maven。
apply plugin: 'maven-publish'
在build.gralde文件中引用maven-publish插件,并配置后,在右侧gradle的面板中即可看到对应的publish任务
执行publishToMavenLocal任务即可将各平台库打包成jar并发布到本地的maven仓库中。我们也可以选择性的发布某一个平台的jar到本地maven仓库中。
执行publish任务即可将各平台库打包并发布到本地的maven仓库中。
对于npm仓库的上传,可直接修改build/js目录下pacakage.json的相关配置,然后执行npm publish命令进行上传
kotlin跨平台技术实际上已经为我们生成了各平台对应的库,在库的使用上与以往没有什么差别。Android和jvm平台可以使用本地或maven仓库中jvm平台的jar包iOS平台可以使用build目录下生成的framework库文件js平台可以将build/js目录作为module使用,或将module上传至npm
下一章我们将继续介绍在多个平台能同时使用的网络库、序列化库,使网络请求相关的代码只需要一份,即可在多个平台运行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。