Zapisywanie danych w lokalnej bazie danych za pomocą biblioteki Room, części Androida Jetpack.
Aplikacje, które przetwarzają duże ilości uporządkowanych danych, mogą korzystać z lokalnego przechowywania tych danych. Najczęstszym zastosowaniem jest przechowywanie w pamięci podręcznej odpowiednich fragmentów danych, aby użytkownik mógł przeglądać treści w trybie offline, gdy urządzenie nie ma dostępu do sieci.
Biblioteka trwałości danych Room zapewnia warstwę abstrakcji nad SQLite, aby umożliwić płynny dostęp do bazy danych przy jednoczesnym wykorzystaniu pełnej mocy SQLite. W szczególności Room zapewnia te korzyści:
- Weryfikacja zapytań SQL w czasie kompilowania.
- Adnotacje ułatwiające pracę, które minimalizują podatny na błędy powtarzalny kod.
- Uproszczone ścieżki migracji baz danych.
Z tych powodów zdecydowanie zalecamy korzystanie z biblioteki Room zamiast bezpośredniego używania interfejsów API SQLite.
Konfiguracja
Aby używać Room w aplikacji, dodaj te zależności do pliku build.gradle
aplikacji.
Kotlin
dependencies { val room_version = "2.8.2" implementation("androidx.room:room-runtime:$room_version") // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See Add the KSP plugin to your project ksp("androidx.room:room-compiler:$room_version") // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor("androidx.room:room-compiler:$room_version") // optional - Kotlin Extensions and Coroutines support for Room implementation("androidx.room:room-ktx:$room_version") // optional - RxJava2 support for Room implementation("androidx.room:room-rxjava2:$room_version") // optional - RxJava3 support for Room implementation("androidx.room:room-rxjava3:$room_version") // optional - Guava support for Room, including Optional and ListenableFuture implementation("androidx.room:room-guava:$room_version") // optional - Test helpers testImplementation("androidx.room:room-testing:$room_version") // optional - Paging 3 Integration implementation("androidx.room:room-paging:$room_version") }
Groovy
dependencies { def room_version = "2.8.2" implementation "androidx.room:room-runtime:$room_version" // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See KSP Quickstart to add KSP to your build ksp "androidx.room:room-compiler:$room_version" // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor "androidx.room:room-compiler:$room_version" // optional - RxJava2 support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - RxJava3 support for Room implementation "androidx.room:room-rxjava3:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // optional - Test helpers testImplementation "androidx.room:room-testing:$room_version" // optional - Paging 3 Integration implementation "androidx.room:room-paging:$room_version" }
Główne komponenty
Room ma 3 główne komponenty:
- Klasa bazy danych zawiera bazę danych i służy jako główny punkt dostępu do połączenia z utrwalonymi danymi aplikacji.
- Jednostki danych reprezentujące tabele w bazie danych aplikacji.
- Obiekty umożliwiające dostęp do danych (DAO) udostępniają metody umożliwiające aplikacji wykonywanie zapytań, aktualizowanie, wstawianie i usuwanie danych w bazie danych.
Klasa bazy danych udostępnia aplikacji instancje obiektów DAO powiązanych z tą bazą danych. Aplikacja może z kolei używać obiektów DAO do pobierania danych z bazy danych jako instancji powiązanych obiektów encji danych. Aplikacja może też używać zdefiniowanych jednostek danych do aktualizowania wierszy w odpowiednich tabelach lub tworzenia nowych wierszy do wstawienia. Rysunek 1 przedstawia relacje między poszczególnymi komponentami Room.

Przykładowa implementacja
W tej sekcji znajdziesz przykładową implementację bazy danych Room z jedną encją danych i jednym obiektem DAO.
Encja danych
Poniższy kod definiuje encję danych User
. Każda instancja User
reprezentuje wiersz w tabeli user
w bazie danych aplikacji.
Kotlin
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String?, @ColumnInfo(name = "last_name") val lastName: String? )
Java
@Entity public class User { @PrimaryKey public int uid; @ColumnInfo(name = "first_name") public String firstName; @ColumnInfo(name = "last_name") public String lastName; }
Więcej informacji o encjach danych w bibliotece Room znajdziesz w artykule Definiowanie danych za pomocą encji Room.
Obiekt umożliwiający dostęp do danych (DAO)
Poniższy kod definiuje obiekt DAO o nazwie UserDao
. UserDao
udostępnia metody, których pozostała część aplikacji używa do interakcji z danymi w tabeli user
.
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM user") fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") fun loadAllByIds(userIds: IntArray): List<User> @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") fun findByName(first: String, last: String): User @Insert fun insertAll(vararg users: User) @Delete fun delete(user: User) }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Delete void delete(User user); }
Więcej informacji o obiektach DAO znajdziesz w artykule Uzyskiwanie dostępu do danych za pomocą obiektów DAO w bibliotece Room.
Baza danych
Poniższy kod definiuje klasę AppDatabase
, która będzie przechowywać bazę danych.
AppDatabase
definiuje konfigurację bazy danych i służy jako główny punkt dostępu aplikacji do utrwalonych danych. Klasa bazy danych musi spełniać te warunki:
- Klasa musi być oznaczona jako
@Database
, która zawiera tablicęentities
z listą wszystkich encji danych powiązanych z bazą danych. - Klasa musi być klasą abstrakcyjną, która rozszerza klasę
RoomDatabase
. - Dla każdej klasy DAO powiązanej z bazą danych klasa bazy danych musi zdefiniować metodę abstrakcyjną, która nie ma argumentów i zwraca instancję klasy DAO.
Kotlin
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Java
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
Uwaga: jeśli Twoja aplikacja działa w jednym procesie, podczas tworzenia instancji obiektu AppDatabase
należy stosować wzorzec projektowy singleton. Każda instancja RoomDatabase
jest dość kosztowna, a dostęp do wielu instancji w ramach jednego procesu jest rzadko potrzebny.
Jeśli aplikacja działa w wielu procesach, w wywołaniu narzędzia do tworzenia bazy danych umieść enableMultiInstanceInvalidation()
. Dzięki temu, gdy w każdym procesie masz instancję AppDatabase
, możesz unieważnić udostępniony plik bazy danych w jednym procesie, a to unieważnienie automatycznie rozprzestrzeni się na instancje AppDatabase
w innych procesach.
Wykorzystanie
Po zdefiniowaniu encji danych, obiektu DAO i obiektu bazy danych możesz użyć tego kodu, aby utworzyć instancję bazy danych:
Kotlin
val db = Room.databaseBuilder( applicationContext, AppDatabase::class.java, "database-name" ).build()
Java
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
Następnie możesz użyć metod abstrakcyjnych z AppDatabase
, aby uzyskać instancję DAO. Z kolei metod z instancji DAO możesz używać do interakcji z bazą danych:
Kotlin
val userDao = db.userDao() val users: List<User> = userDao.getAll()
Java
UserDao userDao = db.userDao(); List<User> users = userDao.getAll();
Dodatkowe materiały
Więcej informacji o bibliotece Room znajdziesz w tych materiałach: