KMM初探

什么是KMM?

在开始使用 KMM 之前,您需要了解 Kotlin。

KMM 全称:Kotlin Multiplatform Mobile)是一个用于跨平台移动开发的 SDK,相比于其他跨平台框架,KMM是原生UI+逻辑共享的理念,由KMM封装成Android(Kotlin/JVM)的aar和iOS(Kotlin/Native)的framework,再提供给View层进行调用。

a45a47064c5aab78124a5e9c53a807bf.jpeg

Kotlin Multiplatform Mobile

KMM使用Kotlin 的多平台功能,您可以使用 Kotlin 语言和技术栈,开发一套可以在多平台之间共享的代码库,用来构建统一的代码逻辑,而不用针对各个平台都去实现自己的一套。

0cd32194d2a9b8be6457fbe39b37ea20.png

Kotlin多平台功能

环境工具准备

为了能够开始使用 KMM,您应该安装以下内容:

  1. Java JDK 版本 11

  2. Ruby and Bundler

  3. Android Studio — 版本 4.2 或更高版本

  4. Xcode — 版本 11.3 或更高版本

  5. Xcode 命令行开发者工具

  6. 适用于 Android Studio 的Kotlin Multiplatform Mobile plugin。在 Android Studio 中,选择 Preferences > Plugins > 在 Marketplace 中搜索插件Kotlin Multiplatform Mobile并安装:

b5cfc9c2bb5da796751fd5890c6e627e.png

kmm plugin

准备就绪,是时候创建您的第一个 KMM 项目了

创建第一个 KMM 项目

使用以下步骤创建您的第一个 KMM 项目:

1、打开Android Studio并点击新建 项目:

95751660f568e7d89d5a1085c4c16a92.png

2、在项目的模板中,向下滚动,您将看到我们现在有了KMM 应用程序。选择它并单击下一步按钮:

1874c9a4cf5af139a558b2db7f3280de.png

3、输入您的项目名称、要使用的最低 SDK,然后单击“下一步”按钮:

5fd471d7cd762217bedcf1dc97927bd5.png

4、更改 Android 和 iOS 的应用程序名称。您还可以更改共享模块名称,这里使用默认值并选择为shared模块添加示例测试:

3eb40819153ddbbc1329a336d68e04cc.png

对于iOS应用程序,可以在regular framework或CocoPods依赖管理器之间切换依赖关系,在环境工具准备中我提到需要为CocoPods安装Ruby 。

  1. 单击“下一步”按钮并等待 Gradle 完成项目设置:

项目加载成功后,现在可以找到项目中所有的app模块:

  • androidApp

  • iosApp

  • shared

3d6dfbc00c1b805e8afe6d2ae447df95.png

image
  1. 配置中选择androidApp 和 iOSApp运行到相应模拟器


434d9c0704e2ede140fc141893745e71.png

image

通过AndroidStudio就可运行iOS,通常使用 Xcode 来开发 iOS 原生应用

KMM 会利用 Gradle 插件,自动调用 Xcode 进行构建,并调起 iOS 模拟器运行

9b965f63f35c13c48a671d3ffc79b35b.png

image

注意:使用 KMM Plugin 建立的工程,会默认使用 Kotlin(.kts 文件)的形式来进行 Gradle 配置,另外,其新建的 iOS 工程,也默认使用 Swift UI 进行开发,且这两项不可以配置,如果需要使用传统的 iOS UI 开发形式,需要以集成的形式来新建 KMM Module

KMM工程结构

KMM 插件建立的 KMM 工程的文件目录结构说明

├── androidApp        # 实际 Android APP Module
├── build.gradle.kts  # 工程根 Gradle 配置
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── iosApp            # 实际的 iOS 工程根目录
├── local.properties
├── settings.gradle.kts
└── shared            # KMM 模块代码目录├── build.gradle.kts  # KMM 模块 Gradle 配置(依赖、插件、构建 Task、cinterop 等配置)└── src # 内部模块形式都为 Gradle 工程 Module├── androidMain    # Android 差异化代码,最终生成 AAR├── commonMain     # 共享模块 API 代码├── iosMain        # iOS 差异化代码,└── nativeInterop  # 默认不会创建,用来存放 *.def 文件,描述与 C/C++ 代码,或 Apple Framework 交互时,构建 klib 的配置

b3c05c2a2eb68fd4787636a5ac1c39b2.jpeg

image

androidApp和iosApp为Android和iOS这两个平台的工程模块,shared为共享逻辑模块,供androidApp和iosApp调用。

打开根目录的settings.gradle.kts:

pluginManagement {repositories {google()gradlePluginPortal()mavenCentral()}
}dependencyResolutionManagement {repositories {google()mavenCentral()}
}rootProject.name = "wb-kmm-demo"
include(":androidApp")
include(":shared")

会发现主项目只include了androidApp和shared这两个子项目,因为这两个项目是Gradle项目

iOS的项目如何引用呢?

The iOS application is produced from an Xcode project. It's stored in a separate directory within the root project. 
Xcode uses its own build system; thus, the iOS application project isn't connected with other parts of the Multiplatform Mobile project via Gradle. 
Instead, it uses the shared module as an external artifact – framework.

iOS作为Xcode项目,储存在根项目的另一个文件夹。Xcode有自己的编译系统,因此iOS项目并不依靠Gradle去和shared工程建立联系,而是依靠将shared工程打包成framework供iOS项目使用。我们可以看一下shared模块编译后的产物,如下图所示:

f358182a5964ebd699184c88264df427.png

image

特定于平台的API和实现

因为在我们的核心目标即双端共享代码。

什么是共享代码呢?让同一份代码能在 Android & iOS 上运行。

怎么实现这个目标呢?简单来说把全部代码分为两个部分,其中一部分就是与平台无关的代码。

啥是平台无关的代码呢?比如我们要编写一个检验手机号的算法,我们认为这个算法的代码是平台无关的,因为输入就是一个字符串,里面的实现就是根据指定的规则来判断这个输入字符串的合法性,期间不涉及任何平台相关特性的访问,比如系统 API 的访问。

但是光有与平台无关的代码是不够的,一旦涉及到与平台相关的访问,例如获取设备版本号或硬件信息等,我们就需要独立于平台去完成它们,这些独立于平台的代码在哪实现?这就有了 AndroidApp 和 iOSApp 这两个模块。在“shared”模块中,我们包含了核心应用程序逻辑,例如类、函数,并使用 Gradle 作为构建系统。

expect/actual 机制 :

ad6a7e7cf10fafbfaa569e84d68454b9.jpeg

image

KMM 里 expect/actual 机制是非常重要的,因为它提供了一种语法技术来解决平台相关的问题。

拿工程例子来说,工程逻辑中使用设备的 版本 号时,这里需要编写特定平台的代码才能实现。这时,expect 就相当于声明一个协议,它定义了我们期望得到的接口或数据,之后各个平台都需要独立地实现这个协议来满足业务需要。

shared模块的实现形式

进入shared模块,看commonMain文件夹下Greeting的实现:

class Greeting {private val platform: Platform = getPlatform()fun greet(): String {return "Hello, ${platform.name}!"}
}

greeting()方法调用platform.name,Platform的实现如下:

interface Platform {val name: String
}expect fun getPlatform(): Platform

Platform是个接口,使用expect关键字来声明getPlatform(),再由Android和iOS通过使用actual关键字分别实现:

Android:

class AndroidPlatform : Platform {override val name: String = "Android ${android.os.Build.VERSION.SDK_INT}"
}actual fun getPlatform(): Platform = AndroidPlatform()

iOS:

import platform.UIKit.UIDeviceclass IOSPlatform: Platform {override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}actual fun getPlatform(): Platform = IOSPlatform()

最后是两端调用实现:

Android:

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {MyApplicationTheme {Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colors.background) {GreetingView(Greeting().greet())}}}}
}@Composable
fun GreetingView(text: String) {Text(text = text)
}

iOS:

import SwiftUI
import sharedstruct ContentView: View {let greet = Greeting().greet()var body: some View {Text(greet)}
}struct ContentView_Previews: PreviewProvider {static var previews: some View {ContentView()}
}
KMM vs Flutter vs RN

与 Flutter 这种框架的思想相反,KMM 是用一套语言生成多个平台特定的字节码,所有的翻译工作由 kotlinc 或 kotlin-nativec 编译器来执行,从某种角度来讲,是『从上到下』;

而 Flutter 的思想是『从下到上』,这也决定了两种框架适用的场景,Flutter 就适合绘制 UI,而 KMM 则是更适合与 UI 无关的逻辑代码,比如:Model 层,网络请求、数据解析、建模等

  • 体积:

  1. 使用 Flutter 需要在 App 包内部增加两个引擎:

  • 一个是 Flutter 的渲染引擎,该引擎使用 C/C++ 开发,直接调用 OpenGL/Skia 的 API 进行绘制,从而摆脱 iOS 的 UIKit 以及 Android 的 View 组件直接渲染成需要的样式,保证样式高度统一

  • 另一个是 Dart 语言的 Runtime,用于解析并运行 Dart 语言编译的 Bundle

这两者减小了开发者的适配成本,但增大了 APP 的包体积(其他类似的跨平台框架,如:React Native 等,也会内置 JavaScript Core 或 V8 引擎)

  1. KMM 针对不同平台生成不同的二进制依赖包,根本上还是调用了 Android、iOS 的原生 API,并不会内置引擎这类文件,对 App 的体积影响相对较小

  • 技术栈:

    • Flutter-->Dart

    • KMM-->Kotlin

    • RN-->JavaScript

  • 适用场景:

    • 由于 Flutter 采用类似 3D 游戏的渲染理念,统一了界面渲染引擎,利用 Dart 可以高度保证双端样式和交互逻辑一致,且几乎不存在界面适配问题,完全抹平了 TextView 和 UILabel 这类控件之间的差异,所以 Flutter 适合于界面构建

    • 而 KMM 并不适合 UI,双端的组件,生命周期、API 差异都比较大,KMM 在技术上可以实现功能,但相当于写了两份代码,失去了意义

Flutter和RN这两者虽然在设计及原理上区别很大,但设计思想上都是采用非原生开发语言在 Android 与 iOS 系统框架之上搭建的“阁楼”上运行,每个采用这些框架的 App 在打包时需要集成语言的 Runtime、框架的底层组件等许多重量级的包与库。并且 JavaScript 或 Dart 与原生开发语言(Java/Kotlin、Objective-C/Swift)之间的交互需要通过“桥接通讯”实现

KMM提出了不同于 RN 与 Flutter 的跨端解决方案,即使用不同的编译器编译同一份代码生成各端的不同产物来达到跨平台的目的,这就是 Kotlin Multiplatform

Kotlin Multiplatform

Kotlin Multiplatform 技术可为多种平台创建应用程序并在平台之间高效重用代码,同时保留原生编程的优势。多平台应用程序将在不同操作系统上运行,例如 iOS、Android、macOS、Windows 和 Linux 等。

27c016ec58560938bb22782af63cddff.png

image

Kotlin 官方开发的多平台框架分为以下几种:

  • 标准 Kotlin(Kotlin Stdlib)

    • 即 Kotlin JVM,由于 Kotlin 最初是基于 JVM 运行的,所以可以使用 Java  的全部功能

  • Kotlin Native

    • 简称 KN,内部对各平台(如:Windows、Linux、macOS、iOS、Android)Native API(不使用 Runtime 的)进行封装,底层使用 LLVM 进行编译,可以使用 Kotlin 调用各平台特定的 API 或基于一些 C/C++ 库的能力,如:OpenGL、OpenCV 等,使多平台共享一套 Kotlin 代码

  • Kotlin JS

    • 基本原理是将 Kotlin 代码翻译成 JavaScript,同时可以调用一些 JavaScript 特定的接口,从而进行 Web 开发

f8f6aa80a24457ff4eb23d5b28dae684.png

image

Compose Multiplatform,一个由JetBrains开发的基于kotlin的声明式UI框架,实现了在Android和iOS之间共享UI,实现了完全跨平台的应用程序:

c7a29c3acbe6d6ad62ba9c6752003e64.jpeg

image

Kotlin Multiplatform Wizard

我们可以使用Kotlin Multiplatform Wizard创建跨平台应用程序。

f847df6b83880cc09ab12265817c86f2.png

image

这里可以选择运行它的平台,如果我们选择与compose多平台共享UI为iOS项目,我们可以创建UI与compose多平台,并运行与iOS和android不使用Swift UI。我们也可以用它创建服务器和桌面项目。

10dea5514932dd13f9939e574a36861a.png


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/757331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型智能大气科学探索之:ChatGPT在大气科学领域建模、数据分析、可视化与资源评估中的高效应用及论文写作

本文深度探讨人工智能在大气科学中的应用,特别是如何结合最新AI模型与Python技术处理和分析气候数据。课程介绍包括GPT-4等先进AI工具,旨在帮助大家掌握这些工具的功能及应用范围。本文内容覆盖使用GPT处理数据、生成论文摘要、文献综述、技术方法分析等…

Java 学习和实践笔记(41):API 文档以及String类的常用方法

JDK 8用到的全部类的文档在这里下载: Java Development Kit 8 文档 | Oracle 中国

docker入门(一)—— docker概述

docker 概述 docker 官网:http://www.docker.com 官网文档: https://docs.docker.com/get-docker/ Docker Hub官网:https://hub.docker.com (仓库) 什么是 docker docker 是一个开源的容器化平台,可以…

FSP40罗德与施瓦茨FSP40频谱分析仪

181/2461/8938产品概述: 频率范围:9千赫至40千兆赫 分辨率带宽:1赫兹至10兆赫 显示的平均噪音水平:-155分贝(1赫兹) 相位噪声:10 kHz时为-113 dB(1Hz) 附加滤波器:100 Hz至5 MHz的通道滤波器和RRC滤波器、1 Hz至3…

数据仓库系列总结

一、数据仓库架构 1、数据仓库的概念 数据仓库(Data Warehouse)是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。 数据仓库通常包含多个来源的数据,这些数据按照主题进行组织和存储&#x…

Springboot+vue的仓库管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频: Springbootvue的仓库管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层…

Leetcode 62. 不同路径

心路历程: 这道题基本就是Q-learning经典迷宫问题的简化版本,所以肯定是用动态规划了,毕竟RL中的时序差分估计法的本身也是来自于MC和动态规划的结合。如果正常正向思维思考的话,首先看不到问题明显的循环结构,考虑递…

秒级生图,大模型 SDXL-turbo、LCM-SDXL 实战案例来了

最近一个月,快速生图成为文生图领域的热点,其中比较典型的两种方式的代表模型分别为SDXL-turbo 和 LCM-SDXL。 SDXL-turbo 模型是 SDXL 1.0 的蒸馏版本,SDXL-Turbo 基于一种称之为对抗扩散蒸馏(ADD)的新颖的训练方法&…

Go 1.22 - 更加强大的 Go 执行跟踪

原文:Michael Knyszek - 2024.03.14 runtime/trace 包含了一款强大的工具,用于理解和排查 Go 程序。这个功能可以生成一段时间内每个 goroutine 的执行追踪。然后,你可以使用 go tool trace 命令(或者优秀的开源工具 gotraceui&a…

Spring Cloud 整合 GateWay

目录 第一章 微服务架构图 第二章 Spring Cloud整合Nacos集群 第三章 Spring Cloud GateWay 第四章 Spring Cloud Alibaba 整合Sentinel 第五章 Spring Cloud Alibaba 整合SkyWalking链路跟踪 第六章 Spring Cloud Alibaba 整合Seata分布式事务 第七章 Spring Cloud 集成Auth用…

[Qt学习笔记]Release后的exe程序在新的电脑上出现“找不到MSVCP140.dll”的错误

1、背景介绍 我们在打包程序的时候一般都会把相关依赖库整体打包,这样程序在新的电脑和环境下就不需要再去配置对应的环境,但是有时候新程序在一台新的电脑运行时会出现“找不到MSVCP140.dll”这种错误,其原因就是在新电脑的操作系统中缺少一…

倒计时 7 天 | 立即加入 GDE 成长计划,飞跃成为谷歌开发者专家

谷歌开发者专家 (Google Developer Experts,GDE),又称谷歌开发者专家项目,是由一群经验丰富的技术专家、具有社交影响力的开发者和思想领袖组成的全球性社区。通过在各项活动演讲以及各个平台上发布优质内容来积极助力开发者、企业和技术社区…

AI助手 - 月之暗面 Kimi.ai

前言 这是 AI工具专栏 下的第四篇,这一篇所介绍的AI,也许是截至今天(204-03-19)国内可访问的实用性最强的一款。 今年年初,一直看到有人推荐 Kimi,不过面对雨后春笋般的各类品质的AI,说实话也有…

windows 多网卡情况dns解析超时问题的排查

最近遇到一个问题 多网卡,多网络环境下,dns解析总是超时。 排查之后发现是dns配置的问题,一个有线网络配置的内网dns,一个无线网络配置的公网dns 访问公网时莫名的时不时出现超时现象 初步排查是dns解析的耗时太长,…

【Go语言】Go语言中的函数

Go语言中的函数 Go语言中,函数主要有三种类型: 普通函数 匿名函数(闭包) 类方法 1 函数定义 Go语言函数的基本组成包括:关键字func、函数名、参数列表、返回值、函数体和返回语句。Go语言是强类型语言&#xff0…

【MySQL | 第五篇】MySQL事务总结

文章目录 5.MySQL事务5.1什么是事务?5.2什么是数据库事务?5.3数据库事务四大特性5.4并发事务带来的问题及解决方案?5.4.1脏读/不可重复读/幻读5.4.2不可重复读和幻读有什么区别?5.4.3解决并发事务带来的问题(1&#xf…

springboot实战笔记

springboot实战笔记 用户模块开发用户登录接口实现根据token获取用户信息检查账号是否可用用户注册接口实现 首页模块开发查询首页分类分页查询首页头条信息查询头条详情 头条模块开发登陆检查头条发布和登录保护拦截器头条根据id回显头条修改头条删除 用户模块开发 用户登录接…

聚观早报 | 阅文去年净利增三成;iQOO Z9系列官宣

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 3月20日消息 阅文去年净利增三成 iQOO Z9系列官宣 英伟达发布全新构架 一加Ace 3V设计细节 小米Civi 4 Pro核心…

章鱼网络 Community Call #19|​开启与 Eigenlayer 的合作

香港时间2024年3月8日12点,章鱼网络举行第19期 Community Call。 在过去的一个月,章鱼网络在成功完成 $NEAR Restaking 功能的安全审计之后,一直在稳步吸引关注。事实上,在整个行业中,我们是极少数已经推出 Restaking …

八大元素,让你的网站科技感拉满,极易落地执行。

Hello,我是大千UI工场,这篇分享各类网页UI的设计风格,就从大家最喜欢的科技感开始吧,欢迎友友们持续关注,我将持续更新,如有设计需求,可以私信我。 在网页UI中,科技感是指通过设计元…