开源|携程机票 App KMM 跨端 KV 存储库 MMKV-Kotlin

本文介绍了携程机票移动端团队基于 MMKV 开发的 MMKV-Kotlin,这是一个支持 Kotlin Multiplatform 的 KV 存储库。MMKV-Kotlin 提供了与原生 MMKV 相似的 API,简化了移动端跨平台存储的集成和使用,尤其适合已有 MMKV 使用经验的开发者。文章详细讲解了 MMKV-Kotlin 的安装、初始化、读写操作,并探讨了其架构设计、实现细节和单元测试。项目已在多个平台上线并开源,为 Kotlin Multiplatform 生态做出贡献。
摘要由CSDN通过智能技术生成

作者简介

 

禹昂,携程移动端资深工程师,专注于 Kotlin 移动端跨平台领域,Kotlin 中文社区核心成员,图书《Kotlin 编程实践》译者。

一、背景

携程机票移动端研发团队自 2021 年始就一直在移动端实践 Kotlin Multiplatform 技术(请见参考链接 1)。由于目前 Kotlin Multiplatform 生态尚处于起步阶段,大部分 Kotlin 开源库都是 JVM only 的,因此在我们团队的日常开发过程中迫切需要一些能够支持 KMM(Kotlin Multiplatform Mobile)的基础库或框架。

在原生移动端开发中,Android SDK 提供了 SharedPreferences,iOS 提供了 NSUserDefaults 用于 KV 存储功能,但这二者在性能要求较高的情况下不能满足需求。后来虽然 Google 推出了 Jetpack Datastore 用于替换 SharedPreferences,但它仅仅支持 Android 平台。

携程的基础框架团队经过一系列评估后决定使用腾讯的开源库 MMKV (参考链接 2)用于满足携程 App 的 KV 存储需求。相较于 SharedPreferences 与 NSUserDefaults,MMKV 拥有更强大的性能;相较于 Jetpack Datastore,MMKV 同时支持多个平台,双端业务逻辑一致性会更好;此外,MMKV 的优势还包括:支持多进程访问、进程被突然杀死时存储依然可以生效等。因此,携程机票移动端研发团队决定基于 MMKV 二次开发,使 MMKV 支持 Kotlin Multiplatform 技术栈。

MMKV-Kotlin 因此应运而生,它拥有极为便捷的集成方式,与 MMKV 高度相似的 API 等诸多特点。对于有 MMKV 使用经验的原移动端开发人员来说,学习迁移成本很低。在经过了大半年的线上实验证明了其稳定性与功能的完整性后,携程机票研发团队决定将其开源,为 Kotlin Multiplatform 开源生态添砖加瓦。MMKV-Kotlin Github 地址详见参考链接 3。

二、简单使用

我们先来简单介绍一下 MMKV-Kotlin 的用法,便于读者对其有个较为直观的认识,也便于后文讨论其内部设计。

2.1 安装与导入

对于 KMM 开发者,在 common source set 中导入 MMKV-Kotlin,在 Gradle 脚本(kts)中添加:

dependencies {     
    implementation("com.ctrip.flight.mmkv:mmkv-kotlin:1.0.0")
}

如果您是使用 Kotlin 编写纯 Android 程序的用户,则导入方式为在 Gradle 脚本(kts)中添加:

dependencies {     
    implementation("com.ctrip.flight.mmkv:mmkv-kotlin-android:1.0.0")
}

对于纯 Android 开发者来说,虽然没有跨平台的需求,但 MMKV-Kotlin 的 API 有针对 Kotlin 语法作出的优化。

注意,截至文章发布前,MMKV-Kotlin 的最新版本是 1.2.0,基于 Kotlin 1.7.0,MMKV 1.2.13。

2.2 初始化

MMKV 在使用前需要进行初始化,由于 MMKV-Android 强依赖于 Context 类型,因此 MMKV-Kotlin 的初始化 API 在两端有所区别,需要在 Android 与 iOS 的主工程或 KMM 的平台相关 source set 中分别初始化:

Android:

import com.ctrip.flight.mmkv.initialize

// In Android source set
fun initializeMMKV(context: Context) {
    val rootDir = initialize(context)
    Log.d("MMKV Path", rootDir)
}

iOS:

import com.ctrip.flight.mmkv.initialize

// In iOS source set
fun initializeMMKV(rootDir: String) {
    initialize(rootDir)
    Log.d("MMKV Path", rootDir)
}

2.3 简单的读写操作

import com.ctrip.flight.mmkv.defaultMMKV

fun demo() {
    val kv = defaultMMKV()

    kv.set("Boolean", true)
    kv.set("Int", Int.MIN_VALUE)
    kv.set("String", "Hello from mmkv")
    
    println("Boolean: ${kv.takeBoolean("Boolean")}")
    println("Int: ${kv.takeInt("Int")}")
    println("String: ${kv.takeString("String")}")
}

使用方式与 MMKV 的 Java 及 Objective-C API 高度相似。

三、架构设计

MMKV core 采用 C++ 编写,其绝大部分功能都在 core 实现。例如 mmap 提供的内存-文件映射、数据根据 protobuf 协议序列化与反序列化、多进程实现等等。core 直接对外暴露 C++ API,在 Win32、POSIX 等系统上可由开发者直接使用。在 core 的外层 MMKV 提供了多种语言的包装,用于支持多种技术栈。例如:Java(Android)、Objective-C(iOS/macOS)、Dart(Flutter)、 JavaScript(React-Native,非腾讯开发与维护)。

MMKV-Kotlin 在底层需要依赖并调用 MMKV,对上希望暴露与 MMKV 类似的 API 并做一些符合语言特性的封装。

MMKV-Kotlin 需要在两个平台相关的 source set 分别集成 MMKV。在 Android source set 中,如果直接集成 MMKV core 需要手动编写 JNI 来做 JVM 层与 C++ 的交互,投入产出比太小, 因此我们选择直接在 Gradle 脚本中通过 Maven 依赖 MMKV-Android,在 Android source set 中直接调用其 Java API。而在 iOS source set 中,由于 Kotlin 目前只与 C 和 Objective-C 有较为完整的互操作能力,因此直接依赖提供 C++ API 的 MMKV core 也并不合适,我们选择在 Gradle 脚本中通过 CocoaPods 依赖 MMKV-iOS,在 iOS source set 中通过其 Objective-C API 完成对 MMKV 的调用。

MMKV-Kotlin 的总体设计见下图:

697326cdad3a3adaa16a20551202ff24.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值