数据库在 App 中的作用
移动 App 的数据库与 Server 数据库不同,其主要目的是为了缓存一些数据,如:历史消息、数据打点、列表数据缓存等,宗旨都是为优化用户体验建立一套简单的数据基础
由于 SQLite 完全开源,且比较轻量(不需要像 MySQL 这样建立一个单独的进程,直接操作 DB 文件),目前,在各类移动端操作系统(包括不限于 Android、iOS、Windows)当中,都会内置 SQLite,以便开发者存取结构化数据
于是,围绕 SQLite 展开的开发框架也越来越多,比如:iOS 上的 FMDB、以及 Apple 官方的 CoreData,Android 上的 SQLiteOpenHelper,以及基于它构建的 GreenDAO、Android 官方的 Room 等等,这些框架使得开发者不需要关注 SQLite 中 C/C++ 一层的 API,大幅降低了移动端数据库的开发成本,使得数据存取变得容易
虽然 SQLite 用途广泛,但 SQLite 也存在着一些性能问题,这些性能问题在数据量比较庞大时,体现地更为明显,近几年也出现了一些面向移动端,基于 NoSQL 或对 SQLite 进行改进数据库框架,如:Realm、WCDB……
那么在 KMM 中,如果需要操作数据库,使用 SQLDelight 框架,无疑是目前比较好的选择
SQLDeilight 简介及特点
SQLDelight 由 Square (开发过 OkHttp、Retrofit、LeakCanary 等一些著名的框架)发起,起初是应用在 Cash App 上,完全使用 Kotlin 进行开发,利用 Kotlin Native 的特性,可以实现 Android、iOS、macOS、Windows 等平台,或 JVM、JavaScript 运行时上的 SQLite 读写操作,也可以借助 JVM,实现对 MySQL、PostgreSQL、HSQL/H2 数据库的支持
利用 SQLDelight 开发的大体思路是先使用 SQL 语句构建表结构和基本的 CURD 操作,根据开发人员编写的 SQL 语句,通过 IDEA 上的 Plugin 进行扫描和解析,从而生成用于建表、迁移及读写数据的 Kotlin 代码,于是在 KMM 模块的 Common 目录中便可调用相关的 CURD 方法,实现对数据库的增删改查
另外,由于双端底层实现的差异(Android 基于 JVM,iOS 基于 Kotlin Native),需要借助 expect/actual
来注入实际的 SQLiteDriver 并进行初始化,才可以正常使用 SQLite 数据库
SQLDelight 框架实现对 SQLite 的基本操作流程,如下图所示

由于其只需要编写符合 SQLite 规范的 SQL 脚本文件(.sq)即可自动生成对应的 Entity、DAO 等,在一定程度上比 Android 上已有的一些框架使用起来还更为简单、方便
使用 SQLDelight 开发的流程
注意:本文使用的是 SQLDelight 1.5.0 版本,需要搭配 Gradle 6.8 及以上的版本使用,使用较低的版本会导致报错!
插件安装
想要使用 SQLDelight 进行开发,首先需要安装官方推出的插件,同 KMM 插件一样,首先需要进入到 Android Studio 设置的『Plugins』页面,只需要在『Marketplace』Tab 中搜索 SQLDelight,根据提示安装,然后重启 Android Studio 即可

它的源码目录链接为:https://github.com/cashapp/sqldelight/tree/master/sqldelight-idea-plugin,如果有兴趣还可以自己手动编译插件
添加 SQLDelight 依赖
由于需要引入 SQLDelight 的 Gradle 插件,所以首先需要在工程根目录的 build.gradle
(或 kts)文件中,加入 SQLDelight 插件依赖
// build.gradle(根目录)
buildscript {
// ...
repositories {
google()
mavenCentral()
}
dependencies {
// 需要在 dependencies 闭包中加入如下依赖
classpath 'com.squareup.sqldelight:gradle-plugin:1.5.0'
}
}
待 Gradle Sync 完成以后,再到 KMM 模块的 build.gradle.kts
文件中,依赖 SQLDelight 插件、主库、Driver 等,同时进行基本配置
// build.gradle.kts(KMM 模块目录中)
plugins {
kotlin("multiplatform")
id("com.android.library")
// 1. 在 plugins 闭包中加入以下依赖
id("com.squareup.sqldelight")
}
// ...
kotlin {
// ...
sourceSets {
// ...
val androidMain by getting {
dependencies {
// 2. 在 androidMain 后面的闭包中,加入 Android 平台的数据库驱动依赖(Android)
implementation("com.squareup.sqldelight:android-driver:1.5.0")
}
}
val iosMain by getting {
dependencies {
// 3. 在 iosMain 后面的闭包中,加入 iOS 平台的数据库驱动依赖(Native)
implementation("com.squareup.sqldelight:native-driver:1.5.0")
}
}
}
}
// ...
// 4. 与 kotlin 闭包同级,加入 sqldelight 闭包,配置数据库基本信息
sqldelight {
// database 方法的首个参数为数据库名称,数据库文件、入口类的命名都以此为准
database("MyKmmAppDB") {
// packageName 为生成 SQLite 操作类的包名,根据情况合理指定即可
packageName = "com.coderyuan.kmm"
// 除包名外,还可以配置生成的类文件目录、sq 文件路径、迁移文件等等,这里先不做过多介绍
}
}
创建 sq 文件目录
这个目录的作用是用来存放数据库表结构及 CRUD 操作的 SQL 语句文件,以便 SQLDelight 插件能够扫描到并自动生成对应的 Kotlin 类文件
其默认的创建规则如下(如在 Gradle 中进行了特殊配置,需要根据配置修改路径):
- 在 commonMain 目录中,与 kotlin 目录平级,取名为:sqldelight
- 需要创建类似 Java/Kotlin 的包结构目录,如:
com/coderyuan/kmm
,包名要与 Gradle 中配置的包名相符,否则会在编译时报错