Эта практическая работа входит в курс «Основы Android Kotlin». Вы получите максимальную пользу от этого курса, если будете выполнять практические работы последовательно. Все практические работы курса перечислены на целевой странице практической работы «Основы Android Kotlin» .
Введение
В большинстве приложений есть данные, которые необходимо сохранять даже после того, как пользователь закрывает приложение. Например, приложение может хранить плейлист, список игровых предметов, записи расходов и доходов, каталог созвездий или данные о сне за определенный период времени. Обычно для хранения постоянных данных используется база данных.
Room — это библиотека для работы с базами данных, входящая в состав Android Jetpack . Room берёт на себя многие задачи по настройке и конфигурированию базы данных и позволяет вашему приложению взаимодействовать с ней, используя обычные вызовы функций. По сути, Room — это уровень абстракции, работающий поверх базы данных SQLite. Терминология Room и синтаксис запросов для более сложных запросов соответствуют модели SQLite.
На рисунке ниже показано, как база данных Room вписывается в общую архитектуру, рекомендуемую в этом курсе.

Что вам уже следует знать
Вам должно быть знакомо:
- Создание базового пользовательского интерфейса (UI) для приложения Android
- Использование действий, фрагментов и представлений.
- Навигация между фрагментами и использование Safe Args (плагина Gradle) для передачи данных между фрагментами.
- Модели представлений, фабрики моделей представлений, а также
LiveDataи их наблюдатели. Эти темы, связанные с компонентами архитектуры, рассматриваются в предыдущей практической работе этого курса. - Базовые знания баз данных SQL и языка SQLite. Для быстрого ознакомления или освежения знаний см. SQLite Primer.
Чему вы научитесь
- Как создать и взаимодействовать с базой данных
Roomдля сохранения данных. - Как создать класс данных, определяющий таблицу в базе данных.
- Как использовать объект доступа к данным (DAO) для сопоставления функций Kotlin с SQL-запросами.
- Как проверить работоспособность вашей базы данных.
Что ты будешь делать?
- Создайте базу данных
Roomс интерфейсом для данных о ночном сне. - Протестируйте базу данных, используя предоставленные тесты.
В этой лабораторной работе вы создадите часть приложения, работающую с базой данных, для отслеживания качества сна. Приложение использует базу данных для хранения данных о сне с течением времени.
Приложение имеет два экрана, представленных фрагментами, как показано на рисунке ниже.
На первом экране, показанном слева, есть кнопки для запуска и остановки отслеживания. На экране отображаются все данные о сне пользователя. Кнопка «Очистить» безвозвратно удаляет все данные, собранные приложением для пользователя.
Второй экран, показанный справа, предназначен для выбора оценки качества сна. В приложении оценка представлена в числовом виде. В целях разработки приложение отображает как значки лиц, так и их числовые эквиваленты.
Поток действий пользователя выглядит следующим образом:
- Пользователь открывает приложение и видит экран отслеживания сна.
- Пользователь нажимает кнопку «Старт» . Время начала фиксируется и отображается на экране. Кнопка «Старт» отключается, а кнопка «Стоп» активируется.
- Пользователь нажимает кнопку «Стоп» . Записывается время окончания и открывается экран качества сна.
- Пользователь выбирает значок качества сна. Экран закрывается, и на экране отслеживания отображаются время окончания сна и качество сна. Кнопка «Стоп» отключается, а кнопка «Старт» активируется. Приложение готово к следующей ночи.
- Кнопка «Очистить» активна, когда в базе данных есть данные. При нажатии кнопки «Очистить » все данные пользователя удаляются без возможности восстановления — сообщение «Вы уверены?» не появляется.
Это приложение использует упрощённую архитектуру, как показано ниже в контексте полной архитектуры. Приложение использует только следующие компоненты:
- Контроллер пользовательского интерфейса
- Просмотреть модель и
LiveData - База данных A Room
Шаг 1: Загрузите и запустите стартовое приложение.
- Загрузите приложение TrackMySleepQuality-Starter с GitHub.
- Соберите и запустите приложение. Приложение отображает пользовательский интерфейс фрагмента
SleepTrackerFragment, но не отображает данные. Кнопки не реагируют на нажатия.
Шаг 2: Проверьте стартовое приложение
- Взгляните на файлы Gradle:
- Файл проекта Gradle
В файлеbuild.gradleуровня проекта обратите внимание на переменные, задающие версии библиотек. Версии, используемые в стартовом приложении, хорошо сочетаются друг с другом и хорошо работают с этим приложением. К моменту завершения этой лабораторной работы Android Studio может предложить вам обновить некоторые версии. Решение о том, обновлять или оставить версии, имеющиеся в приложении, зависит от вас. Если вы столкнётесь со «странными» ошибками компиляции, попробуйте использовать комбинацию версий библиотек, используемую в конечном решении . - Файл модуля Gradle. Обратите внимание на предоставленные зависимости для всех библиотек Android Jetpack, включая
Room, а также зависимости для сопрограмм.
- Взгляните на пакеты и пользовательский интерфейс. Приложение структурировано по функциональным возможностям. Пакет содержит файлы-заглушки, в которые вы будете добавлять код в ходе этой серии практических занятий.
- Пакет
databaseдля всего кода , относящегося к базе данныхRoom. - Пакеты
sleepqualityиsleeptrackerсодержат фрагмент, модель представления и фабрику моделей представления для каждого экрана.
- Взгляните на файл
Util.kt, содержащий функции для отображения данных о качестве сна. Часть кода закомментирована, поскольку ссылается на модель представления, которую вы создадите позже. - Взгляните на папку androidTest (
SleepDatabaseTest.kt). Этот тест поможет вам проверить, работает ли база данных должным образом.
В Android данные представлены в классах данных, а доступ к ним и их изменение осуществляются с помощью вызовов функций. Однако в мире баз данных необходимы сущности и запросы .
- Сущность представляет собой объект или понятие и его свойства, хранящиеся в базе данных. Класс сущности определяет таблицу, и каждый экземпляр этого класса представляет строку в таблице. Каждое свойство определяет столбец. В вашем приложении сущность будет хранить информацию о сне за ночь.
- Запрос — это запрос данных или информации из таблицы базы данных или комбинации таблиц, а также запрос на выполнение действия с данными. Обычно запросы предназначены для получения, добавления и обновления сущностей. Например, можно запросить все зарегистрированные ночи сна, отсортированные по времени начала.
Room выполняет всю сложную работу по переходу от классов данных Kotlin к сущностям, которые можно хранить в таблицах SQLite, и от объявлений функций к запросам SQL.
Необходимо определить каждую сущность как аннотированный класс данных, а взаимодействия — как аннотированный интерфейс, объект доступа к данным (DAO) . Room использует эти аннотированные классы для создания таблиц в базе данных и запросов к ней.

Шаг 1: Создание объекта SleepNight
В этой задаче вы определяете одну ночь сна как аннотированный класс данных.
Для одной ночи сна вам необходимо записать время начала, время окончания и оценку качества.
И вам понадобится идентификатор, чтобы однозначно идентифицировать ночь.
- В пакете
databaseнайдите и откройте файлSleepNight.kt. - Создайте класс данных
SleepNightс параметрами для идентификатора, времени начала (в миллисекундах), времени окончания (в миллисекундах) и числовой оценки качества сна.
- Вам необходимо инициализировать
sleepQuality, установив его на-1, что будет означать, что данные о качестве не были собраны. - Вам также необходимо инициализировать время окончания. Установите его равным времени начала, чтобы обозначить, что время окончания ещё не записано.
data class SleepNight(
var nightId: Long = 0L,
val startTimeMilli: Long = System.currentTimeMillis(),
var endTimeMilli: Long = startTimeMilli,
var sleepQuality: Int = -1
)- Перед объявлением класса добавьте аннотацию
@Entityк классу данных. Назовите таблицуdaily_sleep_quality_table. АргументtableNameнеобязателен, но рекомендуется. Информация о других аргументах представлена в документации.
При появлении запроса импортируйтеEntityи все остальные аннотации из библиотекиandroidx.
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(...)- Чтобы определить
nightIdкак первичный ключ, добавьте к свойствуnightIdаннотацию@PrimaryKey. Установите параметрautoGenerateвtrue, чтобыRoomгенерировал идентификатор для каждой сущности. Это гарантирует уникальность идентификатора для каждой ночи.
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,...- Добавьте аннотацию к оставшимся свойствам с помощью
@ColumnInfo. Настройте имена свойств, используя параметры, как показано ниже.
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,
@ColumnInfo(name = "start_time_milli")
val startTimeMilli: Long = System.currentTimeMillis(),
@ColumnInfo(name = "end_time_milli")
var endTimeMilli: Long = startTimeMilli,
@ColumnInfo(name = "quality_rating")
var sleepQuality: Int = -1
)- Скомпилируйте и запустите свой код, чтобы убедиться в отсутствии ошибок.
В этой задаче вы определите объект доступа к данным (DAO). В Android DAO предоставляет удобные методы для добавления, удаления и обновления базы данных.
При использовании базы данных Room вы обращаетесь к ней, определяя и вызывая функции Kotlin в коде. Эти функции Kotlin сопоставляются с SQL-запросами. Вы определяете эти сопоставления в DAO с помощью аннотаций, а Room создаёт необходимый код.
Представьте себе DAO как определение настраиваемого интерфейса для доступа к вашей базе данных.
Для распространённых операций с базой данных библиотека Room предоставляет удобные аннотации, такие как @Insert , @Delete и @Update . Для всего остального есть аннотация @Query . Вы можете написать любой запрос, поддерживаемый SQLite.
В качестве дополнительного бонуса, когда вы создаете запросы в Android Studio, компилятор проверяет ваши SQL-запросы на наличие синтаксических ошибок.
Для базы данных с данными о сне вам необходимо иметь возможность выполнять следующие действия:
- Вставьте новые ночи.
- Обновите существующую ночь, чтобы обновить время окончания и рейтинг качества.
- Получите конкретную ночь в зависимости от ее тональности.
- Получите все ночи , чтобы вы могли их отобразить.
- Получите последнюю ночь.
- Удалить все записи в базе данных.
Шаг 1: Создайте SleepDatabase DAO
- В пакете
databaseоткройтеSleepDatabaseDao.kt. - Обратите внимание, что
interfaceSleepDatabaseDaoаннотирован@Dao. Все объекты DAO должны быть аннотированы ключевым словом@Dao.
@Dao
interface SleepDatabaseDao {}- Внутри тела интерфейса добавьте аннотацию
@Insert. Под@Insertдобавьте функциюinsert(), которая принимает экземпляр классаEntitySleepNightв качестве своего аргумента.
Вот и всё.Roomсгенерирует весь необходимый код для добавленияSleepNightв базу данных. При вызовеinsert()из кода KotlinRoomвыполняет SQL-запрос для добавления сущности в базу данных. (Примечание: вы можете назвать эту функцию как угодно.)
@Insert
fun insert(night: SleepNight)- Добавьте аннотацию
@Updateс функциейupdate()для одногоSleepNight. Обновляемая сущность — это сущность с тем же ключом, что и переданная. Вы можете обновить некоторые или все остальные свойства сущности.
@Update
fun update(night: SleepNight) Для оставшейся функциональности нет удобной аннотации, поэтому вам придется использовать аннотацию @Query и предоставлять запросы SQLite.
- Добавьте аннотацию
@Queryс функциейget(), которая принимаетLongkeyАргумент и возвращаетSleepNight, допускающий значение NULL. Если параметр отсутствует, вы увидите ошибку.
@Query
fun get(key: Long): SleepNight?- Запрос передается в виде строкового параметра аннотации. Добавьте параметр в
@Query. Сделайте егоString, представляющей собой запрос SQLite.
- Выберите все столбцы из таблицы
daily_sleep_quality_table -
WHEREnightIdсоответствуетkeyаргументу :.
Обратите внимание на:key. Двоеточие в запросе используется для ссылки на аргументы функции.
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")- Добавьте ещё один
@Queryс функциейclear()и SQLite-запросом дляDELETEвсех данных из таблицыdaily_sleep_quality_table. Этот запрос не удаляет саму таблицу.
Аннотация@Deleteудаляет один элемент, и вы могли бы использовать@Deleteи предоставить список ночей для удаления. Недостаток заключается в том, что вам нужно получить или знать содержимое таблицы. Аннотация@Deleteотлично подходит для удаления отдельных записей, но неэффективна для удаления всех записей из таблицы.
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()- Добавьте
@Queryс функциейgetTonight(). Сделайте так, чтобыSleepNight, возвращаемый функциейgetTonight()допускал значение NULL, чтобы функция могла обрабатывать случай, когда таблица пуста. (Таблица пуста в начале и после очистки данных.)
Чтобы получить значение «tonight» из базы данных, напишите SQLite-запрос, который вернет первый элемент списка результатов, отсортированного поnightIdв порядке убывания. ИспользуйтеLIMIT 1чтобы вернуть только один элемент.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?- Добавьте
@Queryс функциейgetAllNights():
- Запрос SQLite должен вернуть все столбцы из
daily_sleep_quality_table, упорядоченные по убыванию. - Метод
getAllNights()возвращает список сущностейSleepNightв видеLiveData.Roomобновляет этиLiveData, что означает, что вам нужно явно получить данные только один раз. - Возможно, вам потребуется импортировать
LiveDataизandroidx.lifecycle.LiveData.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>- Хотя вы не увидите никаких видимых изменений, запустите приложение, чтобы убедиться в отсутствии ошибок.
В этой задаче вы создаете базу данных Room , которая использует Entity и DAO, созданные вами в предыдущей задаче.
Вам необходимо создать абстрактный класс-держатель базы данных с аннотацией @Database . Этот класс имеет один метод, который либо создаёт экземпляр базы данных, если она не существует, либо возвращает ссылку на существующую базу данных.
Получение базы данных Room немного сложнее, поэтому вот общий процесс, прежде чем вы начнете работать с кодом:
- Создайте
public abstractкласс,extends RoomDatabase. Этот класс будет выполнять функцию хранилища базы данных. Класс является абстрактным, посколькуRoomсоздаёт реализацию автоматически. - Добавьте к классу аннотацию
@Database. В аргументах объявите сущности для базы данных и укажите номер версии. - Внутри объекта-
companionопределите абстрактный метод или свойство, возвращающееSleepDatabaseDao.Roomсгенерирует тело автоматически. - Вам нужен только один экземпляр базы данных
Roomдля всего приложения, поэтому сделайтеRoomDatabaseодиночным экземпляром. - Используйте конструктор баз данных
Roomдля создания базы данных только в том случае, если она не существует. В противном случае верните существующую базу данных.
Шаг 1: Создание базы данных
- В пакете
databaseоткройтеSleepDatabase.kt. - В файле создайте
abstractклассSleepDatabase, который расширяетRoomDatabase.
Добавьте к классу аннотацию@Database.
@Database()
abstract class SleepDatabase : RoomDatabase() {}- Вы увидите ошибку из-за отсутствующих сущностей и параметров версии. Аннотация
@Databaseтребует нескольких аргументов, чтобыRoomмог создать базу данных.
- Укажите
SleepNightкак единственный элемент со спискомentities. - Установите
version1При каждом изменении схемы вам придется увеличивать номер версии. - Установите
exportSchemaнаfalse, чтобы не сохранять резервные копии истории версий схемы.
entities = [SleepNight::class], version = 1, exportSchema = false- Базе данных необходимо знать о DAO. В теле класса объявите абстрактное значение, возвращающее
SleepDatabaseDao. Можно иметь несколько DAO.
abstract val sleepDatabaseDao: SleepDatabaseDao- Ниже определите
companionобъект. Этот сопутствующий объект позволяет клиентам получать доступ к методам создания или получения базы данных без создания экземпляра класса. Поскольку единственное назначение этого класса — предоставление базы данных, нет смысла создавать его экземпляр.
companion object {}- Внутри объекта
companionобъявите частную переменнуюINSTANCEдля базы данных, допускающую значение NULL, и инициализируйте её значениемnull. ПеременнаяINSTANCEсохранит ссылку на базу данных после её создания. Это поможет избежать многократного открытия подключений к базе данных, что требует больших затрат.
Добавьте аннотацию @Volatile к INSTANCE . Значение переменной volatile никогда не будет кэшироваться, а все операции записи и чтения будут выполняться в основную память и из неё. Это помогает гарантировать, что значение INSTANCE всегда актуально и одинаково для всех потоков выполнения. Это означает, что изменения, внесённые одним потоком в INSTANCE , немедленно видны всем остальным потокам, и вы не столкнётесь с ситуацией, когда, скажем, два потока обновляют одну и ту же сущность в кэше, что могло бы создать проблему.
@Volatile
private var INSTANCE: SleepDatabase? = null- Ниже
INSTANCE, всё ещё внутри объектаcompanion, определите методgetInstance()с параметромContext, который понадобится конструктору базы данных. Возвращает типSleepDatabase. Вы увидите ошибку, посколькуgetInstance()пока ничего не возвращает.
fun getInstance(context: Context): SleepDatabase {}- Внутри
getInstance()добавьте блокsynchronized{}. Передайтеthis, чтобы получить доступ к контексту.
Несколько потоков могут одновременно запрашивать экземпляр базы данных, что приводит к появлению двух баз данных вместо одной. Эта проблема вряд ли возникнет в этом примере приложения, но возможна в более сложном приложении. Обёртывание кода дляsynchronizedбазы данных означает, что только один поток выполнения одновременно может войти в этот блок кода, что гарантирует однократную инициализацию базы данных.
synchronized(this) {}- Внутри блока synchronized скопируйте текущее значение
INSTANCEв локальную переменнуюinstance. Это позволит воспользоваться функцией Smart Cast , которая доступна только для локальных переменных.
var instance = INSTANCE- Внутри
synchronizedблокаreturn instanceв концеsynchronizedблока. Игнорируйте ошибку несоответствия возвращаемого типа; после завершения вы больше никогда не вернёте значение null.
return instance- Над оператором
returnдобавьте операторif, чтобы проверить, является лиinstancenull, то есть база данных еще не существует.
if (instance == null) {}- Если
instanceравенnull, используйте конструктор баз данных для получения базы данных. В теле оператораifвызовитеRoom.databaseBuilderи укажите переданный вами контекст, класс базы данных и имя базы данныхsleep_history_database. Чтобы устранить ошибку, вам потребуется добавить стратегию миграции иbuild()в следующих шагах.
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database")- Добавьте требуемую стратегию миграции в конструктор. Используйте
.fallbackToDestructiveMigration().
Обычно вам потребуется предоставить объект миграции со стратегией миграции на случай изменения схемы. Объект миграции — это объект, который определяет, как все строки старой схемы преобразуются в строки новой схемы, чтобы данные не терялись. Миграция выходит за рамки данной практической работы. Простое решение — удалить и пересоздать базу данных, что означает потерю данных.
.fallbackToDestructiveMigration()- Наконец, вызовите
.build().
.build()- Назначьте
INSTANCE = instanceкак последний шаг внутри оператораif.
INSTANCE = instance- Ваш окончательный код должен выглядеть так:
@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {
abstract val sleepDatabaseDao: SleepDatabaseDao
companion object {
@Volatile
private var INSTANCE: SleepDatabase? = null
fun getInstance(context: Context): SleepDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}- Создайте и запустите свой код.
Теперь у вас есть все необходимые элементы для работы с базой данных Room . Этот код компилируется и запускается, но вы не можете точно сказать, работает ли он. Поэтому сейчас самое время добавить несколько простых тестов.
Шаг 2: Тестирование SleepDatabase
На этом этапе вы запускаете предоставленные тесты для проверки работоспособности вашей базы данных. Это помогает убедиться в её работоспособности перед началом разработки. Предоставленные тесты являются базовыми. Для производственного приложения вам потребуется протестировать все функции и запросы во всех DAO.
Стартовое приложение содержит папку androidTest . Эта папка androidTest содержит модульные тесты, использующие инструментарий Android. Это замысловатый способ сказать, что для тестов требуется фреймворк Android, поэтому их нужно запускать на физическом или виртуальном устройстве. Конечно, вы также можете создавать и запускать чистые модульные тесты, не использующие фреймворк Android.
- В Android Studio в папке androidTest откройте файл SleepDatabaseTest .
- Чтобы раскомментировать код, выделите весь закомментированный код и нажмите сочетание клавиш
Cmd+/илиControl+/. - Взгляните на файл.
Вот краткий обзор тестового кода, поскольку это еще один фрагмент кода, который можно использовать повторно:
-
SleepDabaseTest— это тестовый класс . - Аннотация
@RunWithидентифицирует исполнителя тестов — программу, которая настраивает и выполняет тесты. - Во время настройки выполняется функция с аннотацией
@Before, которая создаётSleepDatabaseв памяти с объектомSleepDatabaseDao. «В памяти» означает, что эта база данных не сохраняется в файловой системе и будет удалена после выполнения тестов. - Кроме того, при построении базы данных в памяти код вызывает другой специфичный для теста метод —
allowMainThreadQueries. По умолчанию при попытке выполнить запросы в основном потоке возникает ошибка. Этот метод позволяет запускать тесты в основном потоке, что следует делать только во время тестирования. - В тестовом методе, аннотированном
@Test, вы создаёте, вставляете и извлекаетеSleepNightи проверяете их идентичность. Если что-то пойдёт не так, выдаётся исключение. В реальном тесте у вас будет несколько@Testметоды. - После завершения тестирования выполняется функция, аннотированная
@After, для закрытия базы данных.
- Щелкните правой кнопкой мыши тестовый файл на панели «Проект» и выберите «Запустить «SleepDatabaseTest» .
- После выполнения тестов проверьте на панели SleepDatabaseTest , что все тесты пройдены.

Поскольку все тесты пройдены, теперь вы знаете несколько вещей:
- База данных создается корректно.
- Вы можете вставить
SleepNightв базу данных. - Вы можете вернуть
SleepNight. -
SleepNightимеет правильное значение качества.
Проект Android Studio: TrackMySleepQualityRoomAndTesting
При тестировании базы данных необходимо проверить все методы, определённые в DAO. Для завершения тестирования добавьте и выполните тесты для проверки остальных методов DAO.
- Определите таблицы как классы данных, аннотированные
@Entity. Свойства, аннотированные@ColumnInfo, определите как столбцы в таблицах. - Определите объект доступа к данным (DAO) как интерфейс, аннотированный
@Dao. DAO сопоставляет функции Kotlin с запросами к базе данных. - Используйте аннотации для определения функций
@Insert,@Deleteи@Update. - Используйте аннотацию
@Queryсо строкой запроса SQLite в качестве параметра для любых других запросов. - Создайте абстрактный класс, имеющий функцию
getInstance(), которая возвращает базу данных. - Используйте инструментированные тесты для проверки корректной работы вашей базы данных и DAO. Вы можете использовать предоставленные тесты в качестве шаблона.
Курс Udacity:
Документация для разработчиков Android:
-
RoomDatabase -
Database(аннотации) - Вы можете использовать необработанные запросы с
Room -
Roomdatabase.Builder - Тестирование обучения
- Класс
SQLiteDatabase -
Dao - Библиотека персистентности
Room
Другая документация и статьи:
В этом разделе перечислены возможные домашние задания для студентов, работающих над этой лабораторной работой в рамках курса, проводимого преподавателем. Преподаватель должен выполнить следующие действия:
- При необходимости задавайте домашнее задание.
- Объясните учащимся, как следует сдавать домашние задания.
- Оцените домашние задания.
Преподаватели могут использовать эти предложения так часто или редко, как пожелают, и могут свободно задавать любые другие домашние задания, которые они сочтут подходящими.
Если вы работаете с этой лабораторной работой самостоятельно, можете использовать эти домашние задания для проверки своих знаний.
Ответьте на эти вопросы
Вопрос 1
Как указать, что класс представляет собой сущность для хранения в базе данных Room ?
- Сделайте так, чтобы класс расширял
DatabaseEntity. - Добавьте к классу аннотацию
@Entity. - Добавьте к классу аннотацию
@Database. - Сделайте так, чтобы класс расширял
RoomEntity, а также аннотируйте класс@Room.
Вопрос 2
DAO (объект доступа к данным) — это интерфейс, который Room использует для сопоставления функций Kotlin с запросами к базе данных.
Как указать, что интерфейс представляет собой DAO для базы данных Room ?
- Сделайте так, чтобы интерфейс расширял
RoomDAO. - Сделайте так, чтобы интерфейс расширял
EntityDao, а затем реализуйте методDaoConnection(). - Добавьте к интерфейсу аннотацию
@Dao. - Добавьте аннотацию к интерфейсу с помощью
@RoomConnection.
Вопрос 3
Какие из следующих утверждений верны для базы данных Room ? Выберите все подходящие варианты.
- Таблицы для базы данных
Roomможно определить как аннотированные классы данных. - Если вы возвращаете
LiveDataиз запроса,Roomбудет обновлятьLiveData, еслиLiveDataизменится. - Каждая база данных
Roomдолжна иметь один и только один DAO. - Чтобы идентифицировать класс как базу данных
Room, сделайте его подклассомRoomDatabaseи аннотируйте его@Database.
Вопрос 4
Какие из следующих аннотаций можно использовать в интерфейсе @Dao ? Выберите все подходящие варианты.
-
@Get -
@Update -
@Insert -
@Query
Вопрос 5
Как проверить работоспособность вашей базы данных? Выберите все подходящие варианты.
- Напишите инструментированные тесты.
- Продолжайте писать и запускать приложение, пока оно не отобразит данные.
- Замените вызовы методов в интерфейсе DAO вызовами эквивалентных методов в классе
Entity. - Запустите функцию
verifyDatabase()предоставленную библиотекойRoom.
Перейти к следующему уроку:
Ссылки на другие практические занятия по этому курсу см. на целевой странице практических занятий по основам Android Kotlin .
Эта практическая работа входит в курс «Основы Android Kotlin». Вы получите максимальную пользу от этого курса, если будете выполнять практические работы последовательно. Все практические работы курса перечислены на целевой странице практической работы «Основы Android Kotlin» .
Введение
В большинстве приложений есть данные, которые необходимо сохранять даже после того, как пользователь закрывает приложение. Например, приложение может хранить плейлист, список игровых предметов, записи расходов и доходов, каталог созвездий или данные о сне за определенный период времени. Обычно для хранения постоянных данных используется база данных.
Room — это библиотека для работы с базами данных, входящая в состав Android Jetpack . Room берёт на себя многие задачи по настройке и конфигурированию базы данных и позволяет вашему приложению взаимодействовать с ней, используя обычные вызовы функций. По сути, Room — это уровень абстракции, работающий поверх базы данных SQLite. Терминология Room и синтаксис запросов для более сложных запросов соответствуют модели SQLite.
На рисунке ниже показано, как база данных Room вписывается в общую архитектуру, рекомендуемую в этом курсе.

Что вам уже следует знать
Вам должно быть знакомо:
- Создание базового пользовательского интерфейса (UI) для приложения Android
- Использование действий, фрагментов и представлений.
- Навигация между фрагментами и использование Safe Args (плагина Gradle) для передачи данных между фрагментами.
- Модели представлений, фабрики моделей представлений, а также
LiveDataи их наблюдатели. Эти темы, связанные с компонентами архитектуры, рассматриваются в предыдущей практической работе этого курса. - Базовые знания баз данных SQL и языка SQLite. Для быстрого ознакомления или освежения знаний см. SQLite Primer.
Чему вы научитесь
- Как создать и взаимодействовать с базой данных
Roomдля сохранения данных. - Как создать класс данных, определяющий таблицу в базе данных.
- Как использовать объект доступа к данным (DAO) для сопоставления функций Kotlin с SQL-запросами.
- Как проверить работоспособность вашей базы данных.
Что ты будешь делать?
- Создайте базу данных
Roomс интерфейсом для данных о ночном сне. - Протестируйте базу данных, используя предоставленные тесты.
В этой лабораторной работе вы создадите часть приложения, работающую с базой данных, для отслеживания качества сна. Приложение использует базу данных для хранения данных о сне с течением времени.
Приложение имеет два экрана, представленных фрагментами, как показано на рисунке ниже.
На первом экране, показанном слева, есть кнопки для запуска и остановки отслеживания. На экране отображаются все данные о сне пользователя. Кнопка «Очистить» безвозвратно удаляет все данные, собранные приложением для пользователя.
Второй экран, показанный справа, предназначен для выбора оценки качества сна. В приложении оценка представлена в числовом виде. В целях разработки приложение отображает как значки лиц, так и их числовые эквиваленты.
Поток действий пользователя выглядит следующим образом:
- Пользователь открывает приложение и видит экран отслеживания сна.
- Пользователь нажимает кнопку «Старт» . Время начала фиксируется и отображается на экране. Кнопка «Старт» отключается, а кнопка «Стоп» активируется.
- Пользователь нажимает кнопку «Стоп» . Записывается время окончания и открывается экран качества сна.
- Пользователь выбирает значок качества сна. Экран закрывается, и на экране отслеживания отображаются время окончания сна и качество сна. Кнопка «Стоп» отключается, а кнопка «Старт» активируется. Приложение готово к следующей ночи.
- Кнопка «Очистить» активна, когда в базе данных есть данные. При нажатии кнопки «Очистить » все данные пользователя удаляются без возможности восстановления — сообщение «Вы уверены?» не появляется.
Это приложение использует упрощённую архитектуру, как показано ниже в контексте полной архитектуры. Приложение использует только следующие компоненты:
- Контроллер пользовательского интерфейса
- Просмотреть модель и
LiveData - База данных A Room
Шаг 1: Загрузите и запустите стартовое приложение.
- Загрузите приложение TrackMySleepQuality-Starter с GitHub.
- Соберите и запустите приложение. Приложение отображает пользовательский интерфейс фрагмента
SleepTrackerFragment, но не отображает данные. Кнопки не реагируют на нажатия.
Шаг 2: Проверьте стартовое приложение
- Взгляните на файлы Gradle:
- Файл проекта Gradle
В файлеbuild.gradleуровня проекта обратите внимание на переменные, задающие версии библиотек. Версии, используемые в стартовом приложении, хорошо сочетаются друг с другом и хорошо работают с этим приложением. К моменту завершения этой лабораторной работы Android Studio может предложить вам обновить некоторые версии. Решение о том, обновлять или оставить версии, имеющиеся в приложении, зависит от вас. Если вы столкнётесь со «странными» ошибками компиляции, попробуйте использовать комбинацию версий библиотек, используемую в конечном решении . - Файл модуля Gradle. Обратите внимание на предоставленные зависимости для всех библиотек Android Jetpack, включая
Room, а также зависимости для сопрограмм.
- Взгляните на пакеты и пользовательский интерфейс. Приложение структурировано по функциональным возможностям. Пакет содержит файлы-заглушки, в которые вы будете добавлять код в ходе этой серии практических занятий.
- Пакет
databaseдля всего кода , относящегося к базе данныхRoom. - Пакеты
sleepqualityиsleeptrackerсодержат фрагмент, модель представления и фабрику моделей представления для каждого экрана.
- Взгляните на файл
Util.kt, содержащий функции для отображения данных о качестве сна. Часть кода закомментирована, поскольку ссылается на модель представления, которую вы создадите позже. - Взгляните на папку androidTest (
SleepDatabaseTest.kt). Этот тест поможет вам проверить, работает ли база данных должным образом.
В Android данные представлены в классах данных, а доступ к ним и их изменение осуществляются с помощью вызовов функций. Однако в мире баз данных необходимы сущности и запросы .
- Сущность представляет собой объект или понятие и его свойства, хранящиеся в базе данных. Класс сущности определяет таблицу, и каждый экземпляр этого класса представляет строку в таблице. Каждое свойство определяет столбец. В вашем приложении сущность будет хранить информацию о сне за ночь.
- Запрос — это запрос данных или информации из таблицы базы данных или комбинации таблиц, а также запрос на выполнение действия с данными. Обычно запросы предназначены для получения, добавления и обновления сущностей. Например, можно запросить все зарегистрированные ночи сна, отсортированные по времени начала.
Room выполняет всю сложную работу по переходу от классов данных Kotlin к сущностям, которые можно хранить в таблицах SQLite, и от объявлений функций к запросам SQL.
Необходимо определить каждую сущность как аннотированный класс данных, а взаимодействия — как аннотированный интерфейс, объект доступа к данным (DAO) . Room использует эти аннотированные классы для создания таблиц в базе данных и запросов к ней.

Шаг 1: Создание объекта SleepNight
В этой задаче вы определяете одну ночь сна как аннотированный класс данных.
Для одной ночи сна вам необходимо записать время начала, время окончания и оценку качества.
И вам понадобится идентификатор, чтобы однозначно идентифицировать ночь.
- В пакете
databaseнайдите и откройте файлSleepNight.kt. - Создайте класс данных
SleepNightс параметрами для идентификатора, времени начала (в миллисекундах), времени окончания (в миллисекундах) и числовой оценки качества сна.
- Вам необходимо инициализировать
sleepQuality, установив его на-1, что будет означать, что данные о качестве не были собраны. - Вам также необходимо инициализировать время окончания. Установите его равным времени начала, чтобы обозначить, что время окончания ещё не записано.
data class SleepNight(
var nightId: Long = 0L,
val startTimeMilli: Long = System.currentTimeMillis(),
var endTimeMilli: Long = startTimeMilli,
var sleepQuality: Int = -1
)- Перед объявлением класса аннотируйте класс данных
@Entity. Назовите таблицуdaily_sleep_quality_table. Аргумент дляtableNameявляется необязательным, но рекомендуется. Вы можете найти другие аргументы в документации.
Если будет предложено, импортEntityи все другие аннотации из библиотекиandroidx.
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(...)- Чтобы идентифицировать
nightIdв качестве основного ключа, аннотируйтеnightIdнедвижимость@PrimaryKey. Установите параметрautoGenerateвtrue, чтобыRoomгенерировала идентификатор для каждого объекта. Это гарантирует, что идентификатор для каждой ночи уникален.
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,...- Аннотировать оставшиеся свойства
@ColumnInfo. Настройте имена свойств, используя параметры, как показано ниже.
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,
@ColumnInfo(name = "start_time_milli")
val startTimeMilli: Long = System.currentTimeMillis(),
@ColumnInfo(name = "end_time_milli")
var endTimeMilli: Long = startTimeMilli,
@ColumnInfo(name = "quality_rating")
var sleepQuality: Int = -1
)- Создайте и запустите свой код, чтобы убедиться, что у него нет ошибок.
В этой задаче вы определяете объект доступа данных (DAO). На Android DAO предоставляет удобные методы для вставки, удаления и обновления базы данных.
Когда вы используете базу данных Room , вы запросите базу данных, определяя и вызывая функции Kotlin в вашем коде. Эти функции Kotlin отображают запросы SQL. Вы определяете эти отображения в DAO, используя аннотации, а Room создает необходимый код.
Думайте о DAO как о определении пользовательского интерфейса для доступа к вашей базе данных.
Для общих операций базы данных библиотека Room предоставляет удобные аннотации, такие как @Insert , @Delete и @Update . Для всего остального есть аннотация @Query . Вы можете написать любой запрос, который поддерживается SQLite.
В качестве дополнительного бонуса, когда вы создаете свои запросы в Android Studio, компилятор проверяет ваши запросы SQL на наличие синтаксических ошибок.
Для базы данных для сна по ночам сна, вам нужно иметь возможность сделать следующее:
- Вставьте новые ночи.
- Обновите существующую ночь, чтобы обновить время окончания и качественный рейтинг.
- Получите конкретную ночь на основе его ключа.
- Получите все ночи , чтобы вы могли отобразить их.
- Получите последнюю ночь.
- Удалить все записи в базе данных.
Шаг 1: Создайте DAO SleepDatabase DAO
- В пакете
databaseOpenSleepDatabaseDao.kt. - Обратите внимание, что
interfaceSleepDatabaseDaoаннотирован с@Dao. Все DAO должны быть аннотированы с ключевым словом@Dao.
@Dao
interface SleepDatabaseDao {}- Внутри корпуса интерфейса добавьте аннотацию
@Insert. Ниже@Insertдобавьте функциюinsert(), которая принимает экземпляр классаEntityClassSleepNightкак его аргумент.
Вот и все.Roomбудет генерировать весь необходимый код для вставкиSleepNightв базу данных. Когда вы вызовитеinsert()из кода Kotlin,Roomвыполняет SQL -запрос, чтобы вставить объект в базу данных. (Примечание: вы можете вызвать функцию все, что хотите.)
@Insert
fun insert(night: SleepNight)- Добавьте аннотацию
@Updateс функциейupdate()для однойSleepNight. Обновленная сущность - это сущность, которая имеет тот же ключ, что и тот, который передается. Вы можете обновить некоторые или все другие свойства объекта.
@Update
fun update(night: SleepNight) Для оставшейся функциональности нет удобной аннотации, поэтому вы должны использовать аннотацию @Query и снабжение SQLite.
- Добавьте аннотацию
@Queryс функциейget(), которая занимаетLongkeyАргумент и возвращает нулевуюSleepNight. Вы увидите ошибку для отсутствующего параметра.
@Query
fun get(key: Long): SleepNight?- Запрос поставляется в виде струнного параметра для аннотации. Добавьте параметр в
@Query. Сделайте этоString, которая является запросом SQLite.
- Выберите все столбцы в
daily_sleep_quality_table -
WHEREnightIdсоответствует:keyаргумент.
Обратите внимание:key. Вы используете нотацию толстой кишки в запросе для ссылки на аргументы в функции.
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")- Добавьте еще один
@Queryс функциейclear()и запросом SQLite, чтобыDELETEвсе изdaily_sleep_quality_table. Этот запрос не удаляет саму таблицу.
Аннотация@Deleteудаляет один элемент, и вы можете использовать@Deleteи предоставить список ночей для удаления. Недостаток в том, что вам нужно получить или знать, что находится в таблице. Аннотация@Deleteотлично подходит для удаления конкретных записей, но не эффективна для очистки всех записей из таблицы.
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()- Добавьте
@Queryс функциейgetTonight(). СделайтеSleepNightвозвращаемуюgetTonight(), чтобы быть нулевой, чтобы функция могла справиться с случаем, когда таблица пуста. (Таблица пуста в начале, и после очистки данных.)
Чтобы получить «сегодня вечером» из базы данных, напишите запрос SQLite, который возвращает первый элемент списка результатов, упорядоченныхnightIdв порядке убывания. ИспользуйтеLIMIT 1, чтобы вернуть только один элемент.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?- Добавьте
@Queryс функциейgetAllNights():
- Попросите запрос SQLite вернуть все столбцы из
daily_sleep_quality_table, упорядоченного в порядке убывания. - Получите
getAllNights()вернуть список сущностейSleepNightв качествеLiveData.Roomдержит этуLiveDataобновленную для вас, что означает, что вам нужно явно получить данные только один раз. - Возможно, вам потребуется импортировать
LiveDataизandroidx.lifecycle.LiveData.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>- Хотя вы не увидите никаких видимых изменений, запустите свое приложение, чтобы убедиться, что у него нет ошибок.
В этой задаче вы создаете базу данных Room , которая использует Entity и DAO, которые вы создали в предыдущей задаче.
Вам нужно создать класс держателя абстрактного базы данных, аннотированный @Database . Этот класс имеет один метод, который либо создает экземпляр базы данных, если база данных не существует, либо возвращает ссылку на существующую базу данных.
Получение базы данных Room немного задействовано, поэтому вот общий процесс, прежде чем начать с кода:
- Создайте
public abstractкласс, которыйextends RoomDatabase. Этот класс должен действовать как держатель базы данных. Класс абстрактный, потому чтоRoomсоздает реализацию для вас. - Аннотируйте класс с
@Database. В аргументах объявьте объекты для базы данных и установите номер версии. - Внутри
companionобъекта определите абстрактный метод или свойство, которое возвращаетSleepDatabaseDao.Roomбудет генерировать для вас тело. - Вам нужен только один экземпляр базы данных
Roomдля всего приложения, так что сделайтеRoomDatabaseсинглтоном. - Используйте застройщик базы данных
Room, чтобы создать базу данных, только если база данных не существует. В противном случае верните существующую базу данных.
Шаг 1: Создайте базу данных
- В пакете
databaseOpenSleepDatabase.kt. - В файле создайте
abstractкласс под названиемSleepDatabase, который расширяетRoomDatabase.
Аннотируйте класс с@Database.
@Database()
abstract class SleepDatabase : RoomDatabase() {}- Вы увидите ошибку для пропущенных объектов и параметров версии. Аннотация
@Databaseтребует нескольких аргументов, так чтоRoomможет построить базу данных.
- Предоставьте ночью
SleepNightкак единственный предмет со спискомentities. - Установите
versionкак1Всякий раз, когда вы меняете схему, вам придется увеличить номер версии. - Установите
exportSchemaвfalse, чтобы не сохранить резервные копии истории версий схемы.
entities = [SleepNight::class], version = 1, exportSchema = false- База данных должна знать о DAO. Внутри тела класса объявите абстрактную ценность, которая возвращает
SleepDatabaseDao. Вы можете иметь несколько DAO.
abstract val sleepDatabaseDao: SleepDatabaseDao- Ниже определить
companion. Спутниковый объект позволяет клиентам получить доступ к методам создания или получения базы данных без создания подготовки к классу. Поскольку единственной целью этого класса является предоставление базы данных, нет никаких оснований для ее создания.
companion object {}- Внутри объекта
companionобъявите частный нулевый экземплярINSTANCEдля базы данных и инициализируйте его вnull. ПеременнаяINSTANCEбудет соблюдать ссылку на базу данных, как только кто -то будет создан. Это помогает вам избежать многократного открытия соединений с базой данных, что дорого.
Аннотировать INSTANCE с @Volatile . Значение летучей переменной никогда не будет кэшировано, и все записи и чтения будут выполнены в основной памяти и обратно. Это помогает убедиться, что значение INSTANCE всегда актуально и одинаково для всех потоков выполнения. Это означает, что изменения, внесенные одним потоком в INSTANCE , немедленно видны всем другим потокам, и вы не получаете ситуации, когда, скажем, по два потока, каждый из которых обновляет одну и ту же сущность в кэше, что создало бы проблему.
@Volatile
private var INSTANCE: SleepDatabase? = null-
INSTANCEниже, все еще внутри объектаcompanion, определите методgetInstance()с параметромContext, который потребуется застройщику базы данных. Верните типSleepDatabase. Вы увидите ошибку, потому чтоgetInstance()еще ничего не возвращает.
fun getInstance(context: Context): SleepDatabase {}- Inside
getInstance(), добавьтеsynchronized{}блок. Пропуститеthis, чтобы вы могли получить доступ к контексту.
Несколько потоков могут потенциально запрашивать экземпляр базы данных одновременно, что приводит к двум базам данных вместо одной. Эта проблема вряд ли произойдет в этом приложении, но это возможно для более сложного приложения. Обертывание кода, чтобы получить базу данных вsynchronizedозначает, что только один поток выполнения за раз может ввести этот блок кода, что гарантирует, что база данных инициализируется только один раз.
synchronized(this) {}- Внутри синхронизированного блока скопируйте текущее значение
INSTANCEвinstanceлокальной переменной. Это может воспользоваться Smart Cast , который доступен только для локальных переменных.
var instance = INSTANCE- Внутри
synchronizedблокаreturn instanceв концеsynchronizedблока. Игнорировать ошибку несоответствия типа возврата; Вы никогда не вернете NULL, как только закончите.
return instance- Выше оператора
returnдобавьте операторif, чтобы проверить, является лиinstanceнулю, то есть, базы данных пока нет.
if (instance == null) {}- Если
instancenull, используйте строитель базы данных, чтобы получить базу данных. В теле из оператораifвызовитеRoom.databaseBuilderи предоставьте контекст, в котором вы передали, класс базы данных и имя для базы данных,sleep_history_database. Чтобы удалить ошибку, вам придется добавить стратегию миграции иbuild()в следующих шагах.
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database")- Добавьте необходимую стратегию миграции в строитель. Использовать
.fallbackToDestructiveMigration().
Обычно вам нужно предоставить миграционный объект с стратегией миграции, когда схема меняется. Миграционный объект - это объект, который определяет, как вы принимаете все строки со старой схемой и конвертируют их в строки в новой схеме, так что данные не теряются. Миграция выходит за рамки этого коделаба. Простое решение - уничтожить и восстановить базу данных, что означает, что данные теряются.
.fallbackToDestructiveMigration()- Наконец, позвоните
.build().
.build()- Назначить
INSTANCE = instanceкак окончательный шаг внутри оператораif.
INSTANCE = instance- Ваш окончательный код должен выглядеть так:
@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {
abstract val sleepDatabaseDao: SleepDatabaseDao
companion object {
@Volatile
private var INSTANCE: SleepDatabase? = null
fun getInstance(context: Context): SleepDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}- Создайте и запустите свой код.
Теперь у вас есть все строительные блоки для работы с базой данных вашей Room . Этот код компилирует и работает, но вы не можете сказать, действительно ли он работает. Итак, это хорошее время, чтобы добавить некоторые основные тесты.
Шаг 2: Проверьте SleepDatabase
На этом этапе вы запускаете предоставленные тесты, чтобы убедиться, что ваша база данных работает. Это помогает гарантировать, что база данных работает, прежде чем вы нарастаете на нее. Предоставленные тесты являются основными. Для производственного приложения вы будете выполнять все функции и запросы во всех DAO.
Приложение стартера содержит папку AndroidTest . Эта папка AndroidTest содержит модульные тесты, которые включают в себя приборы Android, что является причудливым способом сказать, что тесты нуждаются в платформе Android, поэтому вам необходимо запустить тесты на физическом или виртуальном устройстве. Конечно, вы также можете создавать и запустить чистые модульные тесты, которые не включают в себя платформу Android.
- В Android Studio, в папке AndroidTest , откройте файл SleepDataBasetest .
- Чтобы расстроить код, выберите все комментарии и нажмите сочетание
Cmd+/илиControl+/клавиатуры. - Взгляните на файл.
Вот быстрый проход кода тестирования, потому что это еще один код, который вы можете повторно использовать:
-
SleepDabaseTest- это тестовый класс . - Аннотация
@RunWithидентифицирует тестовый бегун, который является программой, которая устанавливает и выполняет тесты. - Во время настройки функция, аннотированная с
@Before, выполняется, и создается в памятиSleepDatabaseсSleepDatabaseDao. «В памяти» означает, что эта база данных не сохраняется в файловой системе и будет удалена после выполнения тестов. - Также при создании базы данных в памяти код вызывает другой метод, специфичный для теста,
allowMainThreadQueries. По умолчанию вы получаете ошибку, если попытаетесь запустить запросы в главном потоке. Этот метод позволяет запускать тесты в основном потоке, что вы должны делать только во время тестирования. - В методе испытания, аннотированным с
@Test, вы создаете, вставляете и получаетеSleepNight, и утверждаете, что они одинаковы. Если что -то пойдет не так, бросьте исключение. В реальном тесте у вас будет несколько@Testметоды - Когда тестирование выполняется, функция, аннотированная с помощью
@Afterвыполняется для закрытия базы данных.
- Щелкните правой кнопкой мыши тестовый файл на панели проекта и выберите «SleepDataBasetest» .
- После выполнения тестов убедитесь на панели SleepDataBasetest , что прошли все тесты.

Поскольку все тесты прошли, теперь вы знаете несколько вещей:
- База данных создается правильно.
- Вы можете вставить
SleepNightв базу данных. - Вы можете вернуться в
SleepNight. -
SleepNightимеет правильное значение для качества.
Android Studio Project: TrackmysleepQuality и
При тестировании базы данных вам необходимо использовать все методы, определенные в DAO. Чтобы завершить тестирование , добавить и выполнить тесты, чтобы использовать другие методы DAO.
- Определите свои таблицы как классы данных, аннотированные с помощью
@Entity. Определите свойства, аннотированные с@ColumnInfoкак столбцы в таблицах. - Определите объект доступа данных (DAO) как интерфейс, аннотированный с
@Dao. DAO Карты Kotlin функционируют на запросы базы данных. - Используйте аннотации, чтобы определить функции
@Insert,@Deleteи@Update. - Используйте аннотацию
@Queryсо строкой запроса SQLite в качестве параметра для любых других запросов. - Создайте абстрактный класс, который имеет функцию
getInstance(), которая возвращает базу данных. - Используйте инструментальные тесты, чтобы проверить, что ваша база данных и DAO работают, как и ожидалось. Вы можете использовать предоставленные тесты в качестве шаблона.
Курс Udacity:
Документация разработчика Android:
-
RoomDatabase -
Database(аннотации) - Вы можете использовать необработанные запросы в
Room -
Roomdatabase.Builder - Тестирование обучения
-
SQLiteDatabaseClass -
Dao - Библиотека персистентности
Room
Другая документация и статьи:
В этом разделе перечислены возможные домашние задания для студентов, которые работают через этот Codelab в рамках курса, во главе с инструктором. Инструктор должен сделать следующее:
- Назначьте домашнее задание, если это необходимо.
- Сообщите студентам, как отправлять домашние задания.
- Оценка домашних заданий.
Преподаватели могут использовать эти предложения столько, сколько они хотят, и должны свободно назначать любую другую домашнюю работу, которая, по их мнению, является подходящей.
Если вы работаете над этим CodeLab самостоятельно, не стесняйтесь использовать эти домашние задания, чтобы проверить свои знания.
Ответьте на эти вопросы
Вопрос 1
Как вы указываете, что класс представляет собой объект для хранения в базе данных Room ?
- Сделайте класс расширение
DatabaseEntity. - Анотировать класс
@Entity. - Аннотируйте класс с
@Database. - Сделайте класс расширить
RoomEntity, а также аннотировать класс с помощью@Room.
Вопрос 2
DAO (объект доступа к данным) - это интерфейс, который Room использует для картирования функций Kotlin с запросами базы данных.
Как вы указываете, что интерфейс представляет собой DAO для базы данных Room ?
- Сделайте интерфейс расширить
RoomDAO. - Сделайте интерфейс Extend
EntityDao, затем реализуйте методDaoConnection(). - Аннотируйте интерфейс с
@Dao. - Аннотируйте интерфейс с
@RoomConnection.
Вопрос 3
Какие из следующих утверждений верны в базу данных Room ? Выберите все, что применимо.
- Вы можете определить таблицы для базы данных
Roomкак аннотированные классы данных. - Если вы вернете
LiveDataиз запроса,Roomбудет держатьLiveDataв обновленной для вас, если изменитсяLiveData. - Каждая база данных
Roomдолжна иметь один, и только один, дао. - Чтобы идентифицировать класс в качестве базы данных
Room, сделайте его подклассомRoomDatabaseи аннотируйте его@Database.
Вопрос 4
Какие из следующих аннотаций вы можете использовать в своем интерфейсе @Dao ? Выберите все, что применимо.
-
@Get -
@Update -
@Insert -
@Query
Вопрос 5
Как вы можете проверить, что ваша база данных работает? Выберите все, что применимо.
- Напишите инструментальные тесты.
- Продолжайте писать и запустить приложение, пока оно не отобразит данные.
- Замените вызовы на методы в интерфейсе DAO на вызовы эквивалентных методов в классе
Entity. - Запустите функцию
verifyDatabase()предоставленную библиотекойRoom.
Начните на следующий урок:
Ссылки на другие коделабы в этом курсе см. Взъективную целевую страницу CodeLabs Foundals Android Kotlin .