KMM 的依赖类型
KMM 的依赖根据平台分为三类,分别是 Common 依赖、Android 依赖、iOS 依赖,其中 Common 依赖顾明思议,是用于通用逻辑的,这种依赖只能使用基于最标准的 Kotlin 底层能力(不可以耦合 JVM、JS)构建
例如,在 Android 端上比较常用的 Kotlin Reflect、OkHTTP、GSON、Fresco,在 iOS 上比较常用的 AFNetworking、YYModel 之类的库,都不能直接用在 KMM 模块的 Common 代码库中
那么,上面说的这些库能不能让 KMM 继续使用?或者有没有直接可以使用的库?。。。
答案当然是肯定的!
使用 Common 或 Android 依赖
Common 依赖
首先是需要找到能够使用的第三方库,这里推荐一些比较优秀、可以直接使用的 KMM 库,不过这些库可能还需要在各平台的代码库中添加依赖项,以便实现差异化功能或者平台耦合能力
官方 JSON 解析库:https://github.com/Kotlin/kotlinx.serialization
HTTP 请求库:https://github.com/ktorio/ktor
SQLite 操作库:https://github.com/cashapp/sqldelight
这些库的依赖也非常简单,和普通的 Gradle 依赖类似,只需要在 KMM 模块根目录的 build.gradle.kts
文件中添加即可,如下图所示,在 commonMain
变量后面的闭包中,新建一个 dependencies
闭包,即可以按照常规的 Gradle 依赖形式,添加 ktor 的 Common 依赖
![](https://img.coderyuan.com/1622432555498.png)
在 Sync 成功后,便可以使用 Common 能力了
Android 依赖
Android 依赖多用于为实现在 Common 中使用 expect
关键字修饰的方法,提供 Android 平台基础能力支持,比如:网络、图片加载等
Android 依赖添加相对比较简单,且限制较少,唯一需要考虑的就是与现有项目集成时的相互依赖关系,或许,对于现有 App 的架构,为合理利用各类组件或能力,需要参考下图所示的模式进行架构调整
![](https://img.coderyuan.com/1622440042189.png)
由于 KMM 模块可能是放在一个 Android 工程当中的,所以对依赖现有模块会比较简单
依赖一个现有模块
如下图所示,首先我的工程中可能存在一个公共库的模块,假设它叫:mylib,其中还包含一些 Android 平台的工具类
![](https://img.coderyuan.com/1622441070531.png)
![](https://img.coderyuan.com/1622440802749.png)
如果我需要在 KMM 模块的 Android 实现中引入 mylib 库,同时,我还需要调用 OkHTTP,同样在 KMM 模块根目录的 build.gradle.kts
文件中按以下配置添加依赖即可,与 Common 添加依赖形式类似
![](https://img.coderyuan.com/1622441129123.png)
Sync 成功以后,即可在 Android 实现的代码中调用我们需要的模块了
![](https://img.coderyuan.com/1622441253460.png)
iOS 依赖
为 KMM 模块的 iOS 实现添加依赖相对比较麻烦,是这篇文章的重点,由于 iOS 程序并不在 JVM 这种 Runtime 上运行,且 iOS 需要考虑到 Objective-C 和 Swift 之间的调用问题,所以必须以 Kotlin Native 的形式进行交互(PS:其中的核心是 Kotlin Native 底层的 cinterop)
基本原理
Kotlin Native 内部使用 cinterop
来对 Apple Framework 进行扫描,根据 Framework 中的 Headers(.h 文件)获取可以调用的类、方法、变量、常量及他们对应的类型,最终生成 klib
文件
而 klib
文件中包含着针对不同 CPU 架构所编译的二进制文件,以及可供 Kotlin Native 调用的 knm
文件,knm
文件类似 Jar 包中的 .class 文件,是被编译后的 Kotlin 代码,内部将 cinterop
扫描出来的 Objective-C 内容转换成了 Kotlin 对应的内容,以便 IDE 可以进行索引,最终在 KMM 模块中使用 Kotlin 代码进行调用
之所以 KMM(或者说 Kotlin Native) 可以调用 iOS SDK (或者 macOS SDK)中 UIKit、Foundation 等模块中的类、方法等内容,也都是利用了上面的原理和流程实现的
注意:使用纯 Swift 开发的库,目前还不支持与 KMM 进行直接交互,但可以利用 Bridge,先暴露给 Objective-C,只要在 Objective-C 中可以调用,则可以与 KMM 进行交互
而 iOS 的项目终究会使用 LLVM 进行编译,所以还有很关键的一点就是:保证主工程与各类库之间的 Compile、Link 过程正确
那么如果是一个现有的第三方库或工程模块,通常可能会以以下三种形式使用:
- CocoaPods
- Framework
- 源码
因为使用源码集成一个第三方库比较复杂,下面我们以 AFNetworking 为例,依次来介绍 KMM 模块如何与 CocoaPods 和 Fra