Сохранение данных в локальной базе данных с помощью Room Часть Android Jetpack.
Приложения, работающие со значительным объемом структурированных данных, могут получить большую выгоду от сохранения этих данных локально. Чаще всего кэшируются важные данные, чтобы пользователи могли просматривать контент, когда устройство не подключено к сети.
Библиотека персистентности Room предоставляет уровень абстракции над SQLite, обеспечивая удобный доступ к базе данных и позволяя использовать все возможности SQLite. В частности, Room предоставляет следующие преимущества:
- Проверка SQL-запросов во время компиляции.
- Удобные аннотации, которые минимизируют повторяющийся и подверженный ошибкам шаблонный код.
- Оптимизированные пути миграции баз данных.
Мы рекомендуем использовать Room вместо прямого использования SQLite API.
Настроить
Чтобы использовать Room в приложении, добавьте в файл build.gradle.kts модуля следующие зависимости: Для обработки аннотаций в Room 3.0 требуется KSP.
Котлин
dependencies { val room_version = "3.0.3" implementation("androidx.room3:room3-runtime:$room_version") ksp("androidx.room3:room3-compiler:$room_version") }
Классный
dependencies { def room_version = "3.0.3" implementation "androidx.room3:room3-runtime:$room_version" ksp "androidx.room3:room3-compiler:$room_version" }
Основные компоненты
В Room есть три основных компонента:
- Класс базы данных, который содержит базу данных и служит основной точкой доступа для базового подключения к сохраненным данным вашего приложения.
- Сущности данных, которые представляют таблицы в базе данных приложения.
- Объекты доступа к данным (DAO), которые предоставляют функции, позволяющие приложению запрашивать, обновлять, вставлять и удалять данные в базе данных.
Класс базы данных предоставляет вашему приложению экземпляры DAO, связанных с этой базой данных. В свою очередь, приложение может использовать DAO для извлечения данных из базы данных в виде экземпляров связанных объектов сущностей данных. Приложение также может использовать определенные сущности данных для обновления строк из соответствующих таблиц или для создания новых строк для вставки. На рисунке 1 показана взаимосвязь между различными компонентами Room.
Пример реализации
В этом разделе представлен пример реализации базы данных Room с одной сущностью данных и одним DAO.
Сущность данных
В приведенном ниже коде определяется сущность данных User. Каждый экземпляр User представляет собой строку в таблице user в базе данных приложения.
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String, @ColumnInfo(name = "last_name") val lastName: String )
Подробнее о сущностях данных в Room…
Объект доступа к данным (DAO)
В приведенном ниже коде определяется объект DAO под названием UserDao. UserDao предоставляет функции, которые остальная часть приложения использует для взаимодействия с данными в таблице user.
@Dao interface UserDao { @Query("SELECT * FROM user") suspend fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") suspend fun loadAllByIds(userIds: IntArray): List<User> @Query( """ SELECT * FROM user WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1 """ ) suspend fun findByName(first: String, last: String): User @Insert suspend fun insertAll(vararg users: User) @Delete suspend fun delete(user: User) }
Чтобы узнать больше о DAO, ознакомьтесь со статьей Доступ к данным с помощью Room DAO.
База данных
В следующем коде определяется класс AppDatabase для хранения базы данных.
AppDatabase определяет конфигурацию базы данных и служит основной точкой доступа приложения к сохраненным данным. Класс базы данных должен соответствовать следующим условиям:
- Класс должен быть аннотирован с помощью
@Database, который включает массивentitiesсо списком всех сущностей данных, связанных с базой данных. - Класс должен быть абстрактным и расширять
RoomDatabase. - Для каждого класса DAO, связанного с базой данных, класс базы данных должен определять абстрактную функцию, которая не принимает аргументов и возвращает экземпляр класса DAO.
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Примечание. Если ваше приложение выполняется в рамках одного процесса, то при создании экземпляра объекта AppDatabase следует использовать шаблон проектирования "Одиночка". Каждый экземпляр RoomDatabase требует значительных ресурсов, и вам вряд ли понадобится доступ к нескольким экземплярам в рамках одного процесса.
Если ваше приложение выполняется в нескольких процессах, добавьте enableMultiInstanceInvalidation() в вызов конструктора базы данных. Таким образом, если у вас есть экземпляр AppDatabase в каждом процессе, вы можете аннулировать общий файл базы данных в одном процессе, и это аннулирование автоматически распространится на экземпляры AppDatabase в других процессах.
Использование
После того как вы определили сущность данных, DAO и объект базы данных, вы можете использовать следующий код для создания экземпляра базы данных:
val db = Room.databaseBuilder<AppDatabase>(applicationContext, "database-name") .setDriver(AndroidSQLiteDriver()) .build()
После этого вы можете использовать абстрактные функции из AppDatabase, чтобы получить экземпляр DAO. В свою очередь, вы можете использовать функции из экземпляра DAO для взаимодействия с базой данных:
val userDao = db.userDao() val users: List<User> = userDao.getAll()
Дополнительные ресурсы
Чтобы узнать больше о Room, ознакомьтесь со следующими ресурсами: