跪拜 Guibai
← All articles
Android · Android Jetpack

Room 3.0 Ships Under a New Package, Making KMP the Default Path

By 黄林晴 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Room 3.0 is the first version where Kotlin Multiplatform isn't a sidecar — it's the architecture. The package rename and API breakage are deliberate: they force a clean split from the Android-only 2.x line so that shared data layers can target iOS, desktop, and web without carrying Android types into common code.

Summary

Room 3.0 is a hard break from the 2.x line. The library moves to the `androidx.room3` package and Maven coordinates, which lets both versions coexist in a project and avoids transitive dependency clashes. KAPT and Java annotation processing are gone; KSP is now mandatory. The core database API replaces `SupportSQLiteDatabase` and Android `Cursor` with a new `SQLiteDriver` abstraction, and direct transaction and query APIs become suspend functions.

A compatibility wrapper artifact exists for code that still needs `SupportSQLiteDatabase`, but the intended path is coroutine-first. `InvalidationTracker.Observer` is removed in favor of `createFlow()`, and return types like `PagingSource`, RxJava, and LiveData now require explicit DAO return type converters. Room 3.0 also adds JavaScript and WasmJS targets, backed by a `WebWorkerSQLiteDriver` that needs a custom Web Worker, and picks up SQLite features like FTS5, `WITHOUT ROWID`, and Kotlin default parameter recognition.

For teams already building a KMP data layer, this is the release to align on. Android-only projects with thin Room wrappers face a manageable migration centered on imports, KSP, and coroutines; projects with deep `SupportSQLite` or `Cursor` usage will have more to untangle.

Takeaways
Room 3.0 uses the new `androidx.room3` Maven group and package; simply bumping the version number breaks dependency resolution.
KAPT and Java annotation processing are removed — KSP is the only supported compiler plugin.
`SupportSQLiteDatabase`, `SupportSQLiteOpenHelper`, and Android `Cursor` are no longer part of the main API, replaced by `SQLiteDriver` and `SQLiteConnection`.
`runInTransaction` becomes the suspend function `withWriteTransaction`; direct queries return a connection and prepared statement instead of a `Cursor`.
Migration callbacks and `onCreate` now receive `SQLiteConnection` instead of `SupportSQLiteDatabase`.
A temporary `room3-sqlite-wrapper` artifact wraps `SQLiteDriver` back to `SupportSQLiteDatabase` for legacy code.
DAO functions that don't return `Flow` or a registered converter type must be `suspend`; `Executor` configuration is replaced by `CoroutineContext`.
`InvalidationTracker.Observer` is removed; table observation moves to `InvalidationTracker.createFlow()`.
`PagingSource`, RxJava, Guava, and LiveData return types now need explicit `@DaoReturnTypeConverters` registration.
JavaScript and WasmJS targets are added, with `WebWorkerSQLiteDriver` requiring a custom Web Worker that wires up SQLite WASM and OPFS.
Room 3.0 supports `@Fts5`, `WITHOUT ROWID` tables, and recognizes Kotlin default parameter values in entities.
Room 2.x and 3.0 can coexist in the same project because of the package rename, easing incremental migration.
Conclusions

Renaming the package is the most aggressive move here — it's not cosmetic. It prevents the kind of silent ABI mixing that plagued AndroidX migrations where old and new code compiled together but broke at runtime.

The removal of `SupportSQLite` from the main API is the clearest signal that Google is done treating SQLite as an Android implementation detail. The `SQLiteDriver` abstraction is designed to be platform-agnostic from the start.

Requiring KSP and dropping KAPT isn't just about build speed. KAPT's stub generation model doesn't work well with KMP common source sets, so this is a prerequisite for multiplatform compilation to function correctly.

The Web target is real but raw — no default worker ships with the library. That means early adopters will be writing their own SQLite WASM glue, which is a higher bar than flipping a Gradle flag.

DAO return type converters turn what was previously built-in magic into an explicit extension point. This makes the compiler surface smaller and lets non-Android platforms define their own return wrappers without forking Room internals.

Coexistence of 2.x and 3.0 is the practical migration story. Large projects can isolate the database module, upgrade it independently, and let the rest of the app catch up later — no big-bang rewrite required.

Concepts & terms
KSP (Kotlin Symbol Processing)
A Kotlin compiler plugin that processes annotations directly from Kotlin source, avoiding the Java stub generation step that KAPT requires. Room 3.0 mandates KSP because KAPT is incompatible with Kotlin Multiplatform common source sets.
SQLiteDriver
The new platform-agnostic database abstraction in Room 3.0 that replaces `SupportSQLiteDatabase`. It provides connections and prepared statements without exposing Android-specific types like `Cursor`, enabling the same Room code to run on iOS, desktop, and web.
WebWorkerSQLiteDriver
A Room `SQLiteDriver` implementation that runs SQLite inside a Web Worker using WebAssembly and OPFS storage. It requires a custom worker script to handle the communication protocol; no default worker is bundled.
DAO Return Type Converter
A compile-time extension point in Room 3.0 that transforms raw query results into custom return types. Previously built-in support for `PagingSource`, RxJava, Guava, and LiveData now goes through this converter mechanism, which must be explicitly registered on the DAO or database.
InvalidationTracker.createFlow()
Replaces the removed `InvalidationTracker.Observer` API. Returns a `Flow` that emits whenever a specified table is modified, allowing reactive observation to stay within the coroutine model instead of using callback-based observers.
From the discussion

No substantive discussion surfaced.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗