База данных является наиболее распространенным местом, где мобильное приложение хранит свои данные. Наиболее популярной с системой управления базами данных в мобильном приложении является SQLite. И Android SDK предоставляет необходимый функционал для работы с SQLite. Конечно, прежде чем углубляться в особенности SQLite в контексте разработки под Android, необходимо иметь базовое понимание запросов SQL. Для этого можно обратиться к соответствующему руководству на данном сайте - Руководство по SQLite. Здесь же мы будет рассматривать работу с SQLite непосредственно в контексте приложения на Jetpack Compose на Android без отсылки к основам SQLite.
Базы данных SQLite размещаются в файлах (обычно с раширением *.db
), которые зачастую расположены по следующему пути:
/data/data/<имя_пакета>/databases/<имя_базы_данных>.db
Например, если пакет приложения называется "com.example.helloapp", и оно использует базу данных "mydatabase.db", то путь к файлу базы данных будет следующим:
/data/data/com.example.helloapp/databases/mydatabase.db
Для работы с SQLite Jetpack Compose имееет специальную библиотеку Room, которая предоставляет высокоуровневый интерфейс поверх системы базы данных SQLite и которая значительно упрощает взаимодействие с базами данными. Вся схема взаимодействия с базой данных выглядит следующим образом:
Прежде всего для получения данных из базы данных обычно определяется отдельный модуль репозитория. Однако код приложения, в частности, репозиторий не обращается напрямую к базе данных. Вместо этого все операции с базой данных выполняются с использованием комбинации базы данных Room, DAO и сущностей. DAO (Data Access Object - объект доступа к данным) содержит операторы SQL, необходимые репозиторию для добавления, извлечения и удаления данных в базе данных SQLite. Эти инструкции SQL сопоставляются с методами, которые затем вызываются из репозитория для выполнения соответствующего запроса.
Объект базы данных Room предоставляет интерфейс к базовой базе данных SQLite. Он также предоставляет репозиторию доступ к объекту DAO. Приложение должно иметь только один экземпляр базы данных Room, который можyj использовать для доступа к нескольким таблицам базы данных.
Для определения данных, которые хранятся в отдельной таблице, применяются специальные классы - сущности (entity). Сущности определяют схему таблицы в базе данных, имя таблицы, ее столбцы и сопутствующюю информацию. Когда репозиторий получает данные базы данных через DAO, то эти данные как раз представляют объекты классов сущностей. Аналогично, когда репозиторию необходимо добавить в базу данных новые данные, он создает объект сущности и затем вызывает методы добавления, определенные в DAO.
В итоге все взаимодействие с базой данных выглядит следующим образом:
Репозиторий взаимодействует с базой данных Room для получения объекта базы данных, который, в свою очередь, используется для получения ссылок на объект DAO
Репозиторий создает объекты сущностей и настраивает их с данными перед передачей их в DAO
Репозиторий вызывает методы DAO, передавая в них объекты сущностей, которые надо добавить и т.д.
Когда объект DAO получает результат запроса для передачи в репозиторий, он упаковывает эти результаты в объекты сущностей
Объект DAO взаимодействует с базой данных Room для выполнения операций с базой данных и обработки результатов
База данных Room обрабатывает все низкоуровневые взаимодействия с базой данных SQLite, отправляя запросы и получая результаты
Перед началом работы с Room, необходимо настроить конфигурацию проекта и добавить все необходимые зависимости. Первым шагом является добавление плагина ksp и дополнительных библиотек в конфигурацию сборки Gradle. Для этого перейдем в преокте к файлу libs.versions.toml и изменим его следующим образом:
[versions] ................... roomRuntime = "2.6.1" runtimeLivedata = "1.6.5" ksp = "1.9.0-1.0.13" [libraries] ............................ androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" } androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomRuntime" } androidx-room-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomRuntime" } androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" } androidx-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "runtimeLivedata" } [plugins] ....................................... devtoolsKsp = { id = "com.google.devtools.ksp", version.ref = "ksp"}
Далее для добавления плагина ksp изменим файл build.gradle.kts уровня проекта ("build.gradle.kts (Project: HelloApp)") следующим образом:
// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { alias(libs.plugins.androidApplication) apply false alias(libs.plugins.jetbrainsKotlinAndroid) apply false alias(libs.plugins.devtoolsKsp) }
И далее отредактируем файл build.gradle.kts уровня модуля ("build.gradle.kts (Module :app)") следующим образом:
plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.jetbrainsKotlinAndroid) alias(libs.plugins.devtoolsKsp) } ....................... dependencies { implementation(libs.androidx.room.runtime) implementation(libs.androidx.room.ktx) implementation (libs.androidx.runtime.livedata) implementation(libs.androidx.lifecycle.viewmodel.compose) annotationProcessor(libs.androidx.room.room.compiler) ksp(libs.androidx.room.room.compiler) .......................................... }
Затем синхронизируем проект, нажав на кнопку Sync Now