当前位置:   article > 正文

用Kotlin进行跨平台开发,看这一篇就够了

kotlin跨平台

c68dab7bd31c8eed4657544f09e86de4.jpeg

/   今日科技快讯   /

近日,投资公司Altimeter Capital向Meta首席执行官马克·扎克伯格发公开信,建议后者裁汰冗员,并大幅缩减元宇宙项目开支,以此增强投资者信心。

Altimeter Capital首席执行官布拉德·格斯特纳在公开信中写道,扎克伯格需要采取重大措施精简Meta的运营,解决股价大幅下跌的问题。他说:“就像零利率世界中许多其他公司一样,Meta也已经陷入了过度转型的困境中,包括人太多,想法太多,紧迫感太少。Meta需要找回它的魔力。”

/   作者简介   /

本篇文章来自黄林晴的投稿,文章主要分享了如何入门KMM跨平台开发,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。

黄林晴的博客地址:

https://huanglinqing.blog.csdn.net/?type=blog

/   前言   /

近些年,不管是最初的RN还是到现在的Flutter、Compose,他们都在做着一件事——跨平台。

他们的成就主要都是在UI上跨平台,当然Flutter虽然可以处理一些公共的业务逻辑,但目前在业务较重的情况下仍然需要各自处理。  

而KMM却与之相反,接下来让我们来一起了解一下吧~

/   什么是KMM   /

KMM 即 Kotlin Multiplatform Mobile是一个SDK,旨在简化跨平台移动应用程序的开发。通过KMM开发者可以在iOS和Android应用程序之间共享通用代码,并仅在必要时编写特定于平台的代码。 

上面官方的描述说了这么多,简单的来说就是KMM注重业务逻辑跨平台,和Flutter、Compose完全相反。即使如此,在这个都想着跨别人的年代,KMM也称自己并没有说过不会做UI的跨平台...

b8d46d1985142d7c4c509d691339e00b.jpeg

/   KMM的HelloWorld   /

环境配置

这里假设,你已经有了一台Mac、安装了高版本的AndroidStudio(这里不会介绍Xcode的配置),在AndroidStudio中搜索插件Kotlin Multiplatform Mobile并安装,如下图所示。

e1e3057493188781f9e04fcec21a012c.png

由于KMM还不是特别的成熟,所以建议开发者将Kotlin插件也升级到最新版本,避免出现一些兼容性问题。

创建项目

安装好插件并重启后,我们可以创建一个Kotlin Multiplatform App,如下图所示。

f068782dfb574df7439a31c272fd959a.png

输入项目名称,选择对应的配置。

82263e8d1918389f522ec5beff9bfb0e.png

在iOS框架分发列表中,选择常规框架选项 (这里为了简单演示,实际项目根据所需选择即可)。点击Finish就创建了一个KMM的项目。

项目结构

创建完的KMM项目结构如下图所示。

9e83faa3473e68c78215be7b6622977e.jpeg

androidApp、iOSApp就是对应的Android、iOS代码库,这里主要说一下shared共享模块,即存放Android、iOS公共业务逻辑的部分。

共享模块由三个源集组成:androidMain、commonMain和iosMain。源集是一个Gradle概念,用于逻辑上组合在一起的多个文件,其中每个组都有自己的依赖项。在Kotlin Multiplatform中,共享模块中的不同源集可以针对不同的平台。如下图所示。

da204d2dca56d182afac4d0ee1d20dae.png

支持多个目标的多平台库,可以在公共源集commonMain中使用。例如Koin、Apollo和Okio。

android和iOSMain,这些是来自相关生态系统的常规库。可以使用CocoaPods或其他依赖项管理器的原生iOS项目和使用Gradle的Android项目中使用。

运行程序

安装过KMM的插件,可以在AndroidStudio中选择iOS的虚拟机,前提必须是已经在Xcode或其他地方配置了iOS的虚拟机,如图所示。

442a2d24780b44b91454612f48ac478b.png

 我们这里仅运行Android程序,运行结果如下图所示。

54b935be21d6ecc2138ec2948179945d.png

这个结果来自shared模块中commonMain下的Greeting文件,代码如下所示。

  1. class Greeting {
  2.     private val platform: Platform = getPlatform()
  3.     fun greeting(): String {
  4.         return "Hello, ${platform.name}!"
  5.     }
  6. }

在iOS的手机上运行则会显示iOS版本号,这里交给读者自己去尝试了。因为我的电脑配置不允许我安装Xcode...

54e42eca31f48c4d546f8f541020f229.png

/   实现元旦倒计时   /

接着我们看如何实现元旦倒计时的功能,其实就是计算现在距离元旦还有多少天。是不是有点似曾相识~

fc23985eeddc34e2e56bac38d40b8f1c.png

这一部分是公共逻辑,在shared目录中的build.gradle.kts文件中添加配置如下:

  1. val commonMain by getting{
  2.     dependencies {
  3.         implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
  4.     }
  5. }

在shared/src/commonMain/kotlin目录下,创建新的Kotlin文件,代码如下所示:

  1. import kotlinx.datetime.*
  2. fun daysUntilNewYear(): Int {
  3.     val today = Clock.System.todayIn(TimeZone.currentSystemDefault())
  4.     val closestNewYear = LocalDate(today.year + 111)
  5.     return today.daysUntil(closestNewYear)
  6. }

修改Greeting的greet方法如下所示。

  1. fun greeting(): String {
  2.    return "距离元旦还有${daysUntilNewYear()}天"
  3. }

运行程序,结果如下图所示。

a3b38e916d4099d74298c23126d6e749.jpeg

在iOS手机中运行的效果也是一致的。

好吧,这个例子太简单了,稍微来个实用点的例子~

/   实现网络请求功能   /

添加依赖

不管什么业务肯定要用到网络请求的功能,我们来看这部分的公共逻辑该怎么处理。

首先我们将用到依赖添加进来,这里主要有Kotlin协程、序列化(Ktor使用要求)、和Ktor,Ktor是一个可以用于HTTP请求的网络框架,如果读者不熟悉的话可自行查看。代码如下所示。

  1. val commonMain by getting {
  2.             dependencies {
  3.                 implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
  4.                 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
  5.                 implementation("io.ktor:ktor-client-core:$ktorVersion")
  6.                 implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
  7.                 implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
  8.             }
  9.         }

同时我们需要再androidMain和iOSMain目录下添加对应Ktor库,代码如下所示。

  1. val androidMain by getting {
  2.         dependencies {
  3.             implementation("io.ktor:ktor-client-android:$ktorVersion")
  4.         }
  5.     }
  6.     val iosMain by creating {
  7.         dependencies {
  8.             implementation("io.ktor:ktor-client-darwin:$ktorVersion")
  9.         }
  10.     }

这里ktorVersion的版本是2.1.2。

添加接口

这里我们仍然使用「wandroid」中的每日一问接口:

https://wanandroid.com/wenda/list/1/json

与在Compose中使用Paging分页库使用的接口和实体类是一样的,这里就不重复展示了。

创建接口地址类,代码如下所示。

  1. object Api {
  2.     val dataApi = "https://wanandroid.com/wenda/list/1/json"
  3. }

创建HttpUtil类,用于创建HttpClient对象和获取数据的方法,代码如下所示。

  1. class HttpUtil {
  2.     private val httpClient = HttpClient {
  3.         install(ContentNegotiation) {
  4.             json(Json {
  5.                 prettyPrint = true
  6.                 isLenient = true
  7.                 ignoreUnknownKeys = true
  8.             })
  9.         }
  10.     }
  11.     /**
  12.      * 获取数据
  13.      */
  14.     suspend fun getData(): String {
  15.         val rockets: DemoReqData =
  16.             httpClient.get(Api.dataApi).body()
  17.         return "${rockets.data} "
  18.     }
  19. }

这里的代码我们应该都是比较熟悉的,仅仅是换了一个网络请求框架而已。现在公共的业务逻辑已经处理好了,只需要页面端调用方法然后解析数据并展示即可。这里我们仍然以Android实现为例。

32324d2dad85295c21ce8c6ce70e3e28.jpeg

实现页面层

在androidApp下编写Compose代码,代码比较简单,就是点击按钮请求数据,展示展示在文本中,代码如下所示。

  1. setContent {
  2.             MyApplicationTheme {
  3.                 Surface(
  4.                     modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background
  5.                 ) {
  6.                     Column() {
  7.                         val scope = rememberCoroutineScope()
  8.                         var text by remember { mutableStateOf("正在加载") }
  9.                         Button(onClick = {
  10.                             scope.launch {
  11.                                 text = try {
  12.                                     Gson().toJson(HttpUtil().getData())
  13.                                 } catch (e: Exception) {
  14.                                     e.localizedMessage ?: "error"
  15.                                 }
  16.                             }
  17.                         }) {
  18.                             Text(text = "请求数据")
  19.                         }
  20.                         Greeting(text)
  21.                     }
  22.                 }
  23.             }
  24.         }

这里我们并没有解析数据,仅仅是将请求的数据转化为Json串显示在文本中。运行程序,默认显示正在加载,点击按钮显示请求接口的数据。

092ffda52da4e4c804df56eb61644fa7.gif

这样我们就实现了网络请求的功能。

/   写在最后   /

到这里,恭喜你,已经入门了KMM的使用,更多的使用方法需要在实际项目中不断地去总结,去尝试,Jetpack目前也在开发KMM版本,这对KMM发展将会是一个推进~

ba67d5af7806f304ec30bb6a6f869a22.jpeg

~

推荐阅读:

我的新书,《第一行代码 第3版》已出版!

Kotlin Flow响应式编程,基础知识入门

Android gradle 插件升级和 kts 迁移踩坑指南

欢迎关注我的公众号

学习技术或投稿

dc0df8f0b80eb57fb472494646d73e2e.png

1e0e68f9618b177c32d81f026d6ca0c7.jpeg

长按上图,识别图中二维码即可关注

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/1004053
推荐阅读
相关标签
  

闽ICP备14008679号