用了 Room 这么多年,大家都习惯了那套熟悉的注解和生成代码。但 Google 这次直接玩大的:新包名、只生成 Kotlin 代码、彻底抛弃 KAPT,还把同步的 DAO 方法一刀切了。所有数据库操作必须走协程或者响应式类型。
这不是 Google 闲着没事干,而是为了彻底拥抱 Kotlin Multiplatform(KMP)。Room 从出生就死死绑定 Android 的 SupportSQLite,现在想跨平台(Android、iOS、JVM、甚至 Web),只能大破大立,甩掉历史包袱。
四个最扎心的变化
-
全新包名和依赖 以前是 androidx.room:room-runtime,现在变成了 androidx.room3:room3-runtime。 类也从 androidx.room.* 挪到了 android.room3.*。 好处是 2.x 和 3.0 可以并存,方便慢慢迁;坏处是所有 import 都要改一遍。
-
彻底告别 Java 代码生成 Room 3.0 只生成 Kotlin 代码。如果你项目里还有纯 Java 的 Entity 或 DAO,该动手迁移了。Google 说维护两套生成逻辑太累,直接砍掉。
-
只支持 KSP KAPT 和老的 Java 注解处理器直接下线。还好从 Room 2.4 开始就支持 KSP,大部分项目应该已经转过去了。
-
DAO 方法必须异步 这是影响面最广的一个。同步阻塞的方法彻底不让写了。
// ❌ Room 3.0 不允许 @Query("SELECT * FROM users WHERE id = :id") fun getUserById(id: Int): User // ✅ 必须这样 @Query("SELECT * FROM users WHERE id = :id") suspend fun getUserById(id: Int): User // 或者返回 Flow @Query("SELECT * FROM users") fun getAllUsers(): Flow<List<User>>想同步查数据?自己包一层 runBlocking 或者在协程作用域里调用。Google 的态度很清楚:现代 Android(和 KMP)开发,协程已经是标配了。
怎么平滑迁移?
别慌,Google 其实留了路:
- 先换 SQLite 驱动:从 Room 2.7 开始就能用新的 androidx.sqlite 驱动 API,建议现在就开始,别再写 SupportSQLite 的代码了。
- 用兼容层过渡:Room 2.8 提供了 room-sqlite-wrapper,能把新 RoomDatabase 转成老的 SupportSQLiteDatabase,方便逐步替换。
- 再切到 Room 3.0:等稳定版出来,换依赖和包名。因为可以共存,你甚至可以按模块一个一个迁。
- 自定义返回类型(RxJava、LiveData 等)需要用新的 @DaoReturnTypeConverter 注解显式注册。
核心思路:先在 2.x 版本里把底层驱动和调用方式准备好,再跳到 3.0。
最大的亮点:真正跨平台了
Room 3.0 不再是“Android 专属”。通过 KMP,它现在原生支持 JavaScript 和 WebAssembly(WasmJs)。Web 端用 androidx.sqlite:sqlite-web 驱动,基于 Web Worker + Origin Private File System(OPFS)实现持久化。
这意味着同一套 Entity、DAO、Database 定义,可以在 Android、iOS(通过 KMP)、桌面、甚至浏览器里复用。数据层逻辑终于不用每个平台重写一遍了,对做跨平台项目的团队来说,价值很大。
Room 2.x 还能继续用吗?
能,但已经进入维护模式。只会出 bug 修复和安全补丁,不会加新功能了。
如果你现在的项目跑得很稳,不急着动也可以。但如果是新项目,或者准备做 KMP,强烈建议直接上 3.0,哪怕它现在还是 alpha。因为拖得越晚,迁移成本只会越高。
写在最后
Room 3.0 是 Jetpack 向 KMP 全面转型的一个重要信号。Google 这次选择不兼容旧世界,直接拥抱 Kotlin-first、协程优先、更干净的架构。短期内肯定有痛点,但长远看,一个能真正跨平台的 Room,对整个生态都是利好。
你项目里还在用 KAPT 吗?打算什么时候开始准备 Room 3.0 迁移?或者你对强制协程这点有什么看法?欢迎评论区一起讨论。