A Room egy könyvtár az SQLite használatához Androidban, amely a Jetpack része. Absztrakciós réteget biztosít a nyers SQLite felett, automatizálva a táblák létrehozását, a lekérdezések végrehajtását és az adatok Kotlin és Java objektumokká konvertálását. A Android Developers szerint a Room a build fázisban lefordítja az SQL lekérdezéseket, ellenőrizve a szintaxis helyességét és az Entity és táblák közötti kapcsolatokat.
Főbb pontok
A Room egy perzisztencia könyvtár az Android Jetpack csomagból, amely objektum-relációs leképezést biztosít az SQLite számára. A Room három fő problémát old meg a nyers SQLite-tal kapcsolatban: nagymennyiségű boilerplate kód írása a táblák létrehozásához, az SQL lekérdezések fordítási időben történő ellenőrzésének hiánya, és a Cursor kézi konvertálása objektumokká.
A könyvtár egy annotációs fordítót (kapt vagy KSP) használ, amely a build fázisban generálja az absztrakt RoomDatabase és DAO osztályok implementációját. Ez garantálja, hogy a SQL szintaxis hibák és típus-eltérések az alkalmazás elindítása előtt kerülnek felismerésre, nem runtime-ban, a Google Play-en történő közzététel után.
A Google I/O 2023 szerint a Room-ot az Android-alkalmazások 68%-a használja, amelyek helyi adatokkal dolgoznak. Ez az eszközön történő adattárolás szabványa, amelyet a Google ajánl minden új projekthez — az elavult SQLiteOpenHelper és ContentProvider helyett.
Alkalmazza a Room-ot olyan projektekben, ahol szükség van a szerveradatok helyi gyorsítótárazására, offline módra, vagy strukturált felhasználói adatok tárolására összetett SQL lekérdezések lehetőségével.
A Room az Android Jetpack része, és hivatalosan ajánlott a Google által minden új projekthez, amely helyi adatokkal dolgozik. A Realm-től vagy ObjectBox-tól eltérően a Room natív SQLite-ot használ, ami garantálja a kompatibilitást bármely harmadik féltől származó adatbázis-kezelő eszközzel — a DB Browser-től a DataGrip-ig. A fejlesztő megnyithatja az alkalmazás .db fájlját, és közvetlenül végrehajthat SQL lekérdezéseket, ami megkönnyíti a hibakeresést és az adatelemzést a fejlesztés során.
Entity egy @Entity annotációval ellátott adatosztály, amelyet a Room adatbázis táblává alakít. Az osztály minden mezője a tábla egy oszlopává válik, minden példánya pedig egy sorrá. A Room reflexiót használ a mezők eléréséhez, ezért a @PrimaryKey annotáció szükséges a kötelező azonosítóhoz.
A @Entity annotáció jelzi a Room-nak, hogy az osztály egy tábla. A tableName paraméter megadja a tábla nevét, ha az eltér az osztály nevétől. A @PrimaryKey határozza meg az elsődleges kulcsot az autoGenerate = true segítségével történő automatikus generálás lehetőségével.
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(name = "full_name")
val name: String,
@Ignore
val tempData: String?
)
@ColumnInfo megadja az oszlop nevét a táblában, ha az eltér a Kotlin mező nevétől. A @Ignore kizárja a mezőt a táblából — az nem kerül mentésre az adatbázisba. A @ForeignKey külső kulcsokat ír le a táblák közötti kapcsolatokhoz kaszkád műveletekkel törléskor vagy frissítéskor.
A Room támogatja a beágyazott objektumokat a @Embedded annotáción keresztül. A beágyazott osztály mezői a szülő tábla oszlopaiba kerülnek egy előtaggal a névütközések elkerülése érdekében. Például egy Address osztály city és street mezőkkel, amely be van ágyazva a User-be, létrehozza az address_city és address_street oszlopokat a users táblában, kiküszöbölve a külön táblák létrehozásának szükségességét egyszerű értékobjektumok számára.
A Room csak primitív típusokat és azok burkolóit támogatja. Listák, Date vagy egyedi típusok tárolásához a @TypeConverter használatos — statikus konverziós metódusok az egyedi típus és az SQLite primitív között, például a List és egy JSON karakterlánc között.
DAO (Data Access Object) egy @Dao annotációval ellátott interfész vagy absztrakt osztály, amely az adatok eléréséhez szükséges metódusokat tartalmazza. Minden metódus egy SQL művelettel van ellátva: @Insert, @Update, @Delete vagy @Query egy explicit SQL lekérdezéssel.
A @Query annotáció egy SQL karakterláncot fogad, amelyet a Room fordítási időben ellenőriz a szintaxis helyessége és az oszlopnevek Entity mezőkkel való egyezése szempontjából. A Room támogatja a paraméterezett lekérdezéseket a :paramName szintaxis segítségével.
@Dao
interface UserDao {
@Query("SELECT * FROM users WHERE id = :userId")
suspend fun getUserById(userId: Int): User?
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUser(user: User)
@Query("SELECT * FROM users ORDER BY name ASC")
fun getAllUsers(): Flow<List<User>>
}
@Insert támogatja az OnConflictStrategy stratégiákat a duplikált rekordok beszúrásakor fellépő konfliktusok kezelésére. Flow visszatérési típusként biztosítja a UI reaktív frissítését a tábla minden adatváltozásakor — a feliratkozás automatikusan újraindul minden INSERT, UPDATE vagy DELETE esetén.
A @Transaction annotáció garantálja több művelet atomi végrehajtását egyetlen tranzakciós blokkban. A Room zárolja az adatbázist a végrehajtás idejére, megakadályozva a versenyhelyzetet több szál párhuzamos hozzáférése esetén.
RoomDatabase egy absztrakt osztály, amely egyesíti az Entity-t és a DAO-t egyetlen adatbázis-hozzáférési pontba. A Room.databaseBuilder segítségével jön létre a séma verziójának és az Entity osztályok listájának megadásával. Az adatbázis-példányt singleton-ként javasolt létrehozni lazy-delegáton keresztül a többszörös kapcsolatok elkerülése érdekében.
Migráció a Room-ban egy Migration osztály, amely egy SQL szkriptet ír le a séma régi verziójáról az újra való áttéréshez. Ha a séma változásakor nem biztosítanak migrációt, a Room IllegalStateException-t dob. Ez véd a felhasználói adatok véletlen elvesztése ellen az alkalmazás frissítésekor.
val migration_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE users ADD COLUMN age INTEGER NOT NULL DEFAULT 0")
}
}
val db = Room.databaseBuilder(
getApplication(),
AppDatabase::class.java,
"app_database"
).addMigrations(migration_1_2)
.build()
A fejlesztéshez használható a fallbackToDestructiveMigration, amely törli a régi adatbázist és újat hoz létre verzióeltérés esetén. Ez a mód csak hibakeresésre szolgál — éles kiadásokban kötelező migrációkat írni.
Az adatbázis teszteléséhez a Room egy speciális Room.inMemoryTestBuilder osztályt biztosít, amely az adatbázist a RAM memóriában hozza létre lemezre mentés nélkül. Minden teszt befejezése után az adatbázis automatikusan megsemmisül, garantálva a tesztforgatókönyvek teljes elkülönítését. Az android-arch-core-testing könyvtárral kombinálva a fejlesztő kezelheti az adatbázis életciklusát és ellenőrizheti a migrációk helyességét anélkül, hogy kézzel kellene törölnie az állapotot.
A Room teljesítménye közvetlenül függ a lekérdezések és indexek szerkezetétől. A lassú lekérdezések elemzéséhez a Room biztosítja az enableQueryCallback jelzőt, amely naplózza az összes SQL lekérdezést a végrehajtási idővel együtt. A fejlesztő ezt a naplót használhatja a 100 ezredmásodpercnél tovább tartó lekérdezések megtalálására és optimalizálására összetett indexek hozzáadásával a @Index annotáción keresztül az @Entity-ben, vagy az allekérdezések közvetlen JOIN kapcsolatokká írásával a @Relation segítségével.
A Room támogatja az adatbázis titkosítását is az SQLCipher-en keresztül. A net.zetetic:android-database-sqlcipher könyvtár csatlakoztatása és a SupportFactory használata a standard helyett biztosítja az összes adat transzparens titkosítását a lemezen anélkül, hogy módosítani kellene a DAO lekérdezéseket és az Entity szerkezetét. Ez szükséges a személyes felhasználói adatokkal dolgozó alkalmazások számára, és megfelel a GDPR és az orosz 152-FZ személyes adatok védelméről szóló törvény követelményeinek. A titkosítási jelszó tárolható az Android Keystore-ban a rootolt eszközökön található eszközökkel történő kinyerés elleni védelem érdekében.
A Room natívan támogatja a Kotlin Coroutines-t a 2.1-es verziótól kezdve. A DAO metódusok lehetnek suspend függvények, amelyek a háttérben hajtanak végre lekérdezéseket anélkül, hogy blokkolnák a fő szálat. A Room automatikusan kezeli a diszpécsereket, a Dispatchers.IO-t használva az olvasási és írási lekérdezésekhez.
Reaktív lekérdezésekhez a Room Flow-t ad vissza — egy hideg adatfolyamot, amely új értéket bocsát ki az érintett tábla minden változásakor. A ViewModel a Flow-ra iratkozik fel a stateIn vagy collect segítségével, biztosítva a UI automatikus frissítését az adapter manuális értesítése nélkül.
A Room támogatja a Paging 3-at is egy speciális PagingSource implementáción keresztül, amely az adatokat oldalanként tölti be az SQLite-ból. Ez hatékony a több ezer rekordot tartalmazó nagy listákhoz: a Paging 3 csak a képernyőn látható sorokat tölti be, és automatikusan frissíti azokat az adatbázis változásai esetén.
Használja a Paging 3-at a Room-mal hírfolyam, műveleti napló vagy terméklista megjelenítésekor offline hozzáféréssel és végtelen görgetéssel.
Gyakran Ismételt Kérdések
A Room automatizálja a táblák létrehozását, a Cursor objektummá konvertálását és az SQL ellenőrzését fordítási időben. Az SQLiteOpenHelper megköveteli a séma kézi írását, a Cursor feldolgozását, és nem ellenőrzi a lekérdezéseket az alkalmazás elindítása előtt, ami növeli a hibák kockázatát.
Igen, az Entity változtatásakor (mező hozzáadása/eltávolítása, típus megváltoztatása) migráció szükséges. Enélkül a Room IllegalStateException-t dob induláskor. Fejlesztéshez bekapcsolható a fallbackToDestructiveMigration, de a kiadásban kötelezőek a helyes migrációs szkriptek.
A Room támogatja a @ForeignKey-t kaszkád műveletekhez és a @Relation-t beágyazott objektumokhoz. Összetett JOIN lekérdezésekhez a @Transaction annotációt használják @Query-vel, amely POJO-t ad vissza beágyazott entitásokkal a @Embedded és @Relation segítségével.
Igen, a Room teljesen kompatibilis a Java-val. A suspend függvények helyett LiveData vagy RxJava Observable, a Flow helyett LiveData használható. A Room Java-val ugyanazokat az annotációkat támogatja, de több boilerplate kódot igényel aszinkron műveletekhez.
A Room támogatja a titkosítást a Zetetic SQLCipher-jén keresztül. A Room.databaseBuilder helyett használja a SupportFactory-t a net.zetetic:android-database-sqlcipher könyvtárból, átadva a titkosítási jelszót. A lemezen lévő összes adat transzparens módon titkosítva lesz a DAO lekérdezések számára.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is