Библиотека room подключение android studio

Урок 5. Room. Основы

Библиотека Room предоставляет нам удобную обертку для работы с базой данных SQLite. В этом уроке рассмотрим основы. Как подключить к проекту. Как получать, вставлять, обновлять и удалять данные.

Полный список уроков курса:

Подключение к проекту

В build.gradle файл проекта добавьте репозитарий google()

В build.gradle файле модуля добавьте dependencies:

Если у вас студия ниже 3.0 и старые версии Gradle и Android Plugin, то подключение будет выглядеть так:

Room имеет три основных компонента: Entity, Dao и Database. Рассмотрим их на небольшом примере, в котором будем создавать базу данных для хранения данных по сотрудникам (англ. — employee).

При работе с Room нам необходимо будет писать SQL запросы. Если вы не знакомы с ними, то имеет смысл прочесть хотя бы основы.

Entity

Аннотацией Entity нам необходимо пометить объект, который мы хотим хранить в базе данных. Для этого создаем класс Employee, который будет представлять собой данные сотрудника: id, имя, зарплата:

Класс помечается аннотацией Entity. Объекты класса Employee будут использоваться при работе с базой данных. Например, мы будем получать их от базы при запросах данных и отправлять их в базу при вставке данных.

Этот же класс Employee будет использован для создания таблицы в базе. В качестве имени таблицы будет использовано имя класса. А поля таблицы будут созданы в соответствии с полями класса.

Аннотацией PrimaryKey мы помечаем поле, которое будет ключом в таблице.

В следующих уроках мы рассмотрим возможности Entity более подробно.

В объекте Dao мы будем описывать методы для работы с базой данных. Нам нужны будут методы для получения списка сотрудников и для добавления/изменения/удаления сотрудников.

Описываем их в интерфейсе с аннотацией Dao.

Методы getAll и getById позволяют получить полный список сотрудников или конкретного сотрудника по id. В аннотации Query нам необходимо прописать соответствующие SQL-запросы, которые будут использованы для получения данных.

Обратите внимание, что в качестве имени таблицы мы используем employee. Напомню, что имя таблицы равно имени Entity класса, т.е. Employee, но в SQLite не важен регистр в именах таблиц, поэтому можем писать employee.

Для вставки/обновления/удаления используются методы insert/update/delete с соответствующими аннотациями. Тут никакие запросы указывать не нужно. Названия методов могут быть любыми. Главное — аннотации.

В следующих уроках мы рассмотрим возможности Dao и его аннотаций более подробно.

Database

Аннотацией Database помечаем основной класс по работе с базой данных. Этот класс должен быть абстрактным и наследовать RoomDatabase.

В параметрах аннотации Database указываем, какие Entity будут использоваться, и версию базы. Для каждого Entity класса из списка entities будет создана таблица.

В Database классе необходимо описать абстрактные методы для получения Dao объектов, которые вам понадобятся.

Практика

Все необходимые для работы объекты созданы. Давайте посмотрим, как использовать их для работы с базой данных.

Database объект — это стартовая точка. Его создание выглядит так:

Используем Application Context, а также указываем AppDatabase класс и имя файла для базы.

Учитывайте, что при вызове этого кода Room каждый раз будет создавать новый экземпляр AppDatabase. Эти экземпляры очень тяжелые и рекомендуется использовать один экземпляр для всех ваших операций. Поэтому вам необходимо позаботиться о синглтоне для этого объекта. Это можно сделать с помощью Dagger, например.

Если вы не используете Dagger (или другой DI механизм), то можно использовать Application класс для создания и хранения AppDatabase:

Не забудьте добавить App класс в манифест

В коде получение базы будет выглядеть так:

Из Database объекта получаем Dao.

Теперь мы можем работать с Employee объектами. Но эти операции должны выполняться не в UI потоке. Иначе мы получим Exception.

Добавление нового сотрудника в базу будет выглядеть так:

Метод getAll вернет нам всех сотрудников в List

Получение сотрудника по id:

Обновление данных по сотруднику.

Room будет искать в таблице запись по ключевому полю, т.е. по id. Если в объекте employee не заполнено поле id, то по умолчанию в нашем примере оно будет равно нулю и Room просто не найдет такого сотрудника (если, конечно, у вас нет записи с >

Аналогично обновлению, Room будет искать запись по ключевому полю, т.е. по id

Давайте для примера добавим еще один тип объекта — Car.

Описываем Entity объект

Теперь Dao для работы с Car объектом

Будем считать, что нам надо только читать все записи, добавлять новые и удалять старые.

В Database необходимо добавить Car в список entities и новый метод для получения CarDao

Читайте также:  Как убрать с рабочего стола андроид новости гугле

Т.к. мы добавили новую таблицу, изменилась структура базы данных. И нам необходимо поднять версию базы данных до 2. Но об этом мы подробно поговорим в Уроке 12. А пока можно оставить версию равной 1, удалить старую версию приложения и поставить новую.

UI поток

Повторюсь, операции по работе с базой данных — синхронные, и должны выполняться не в UI потоке.

В случае с Query операциями мы можем сделать их асинхронными используя LiveData или RxJava. Об этом еще поговорим в следующих уроках.

В случае insert/update/delete вы можете обернуть эти методы в асинхронный RxJava. В моем блоге есть статья на эту тему.

Также, вы можете использовать allowMainThreadQueries в билдере создания AppDatabase

В этом случае вы не будете получать Exception при работе в UI потоке. Но вы должны понимать, что это плохая практика, и может добавить ощутимых тормозов вашему приложению.

Переход на Room

Если вы надумали с SQLite мигрировать на Room, то вот пара полезных ссылок по этой теме:

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Полный список

Библиотека Room предоставляет нам удобную обертку для работы с базой данных SQLite. В этом уроке рассмотрим основы. Как подключить к проекту. Как получать, вставлять, обновлять и удалять данные.

Полный список уроков курса:

Подключение к проекту

В build.gradle файл проекта добавьте репозитарий google()

В build.gradle файле модуля добавьте dependencies:

Если у вас студия ниже 3.0 и старые версии Gradle и Android Plugin, то подключение будет выглядеть так:

Room имеет три основных компонента: Entity, Dao и Database. Рассмотрим их на небольшом примере, в котором будем создавать базу данных для хранения данных по сотрудникам (англ. — employee).

При работе с Room нам необходимо будет писать SQL запросы. Если вы не знакомы с ними, то имеет смысл прочесть хотя бы основы.

Entity

Аннотацией Entity нам необходимо пометить объект, который мы хотим хранить в базе данных. Для этого создаем класс Employee, который будет представлять собой данные сотрудника: id, имя, зарплата:

Класс помечается аннотацией Entity. Объекты класса Employee будут использоваться при работе с базой данных. Например, мы будем получать их от базы при запросах данных и отправлять их в базу при вставке данных.

Этот же класс Employee будет использован для создания таблицы в базе. В качестве имени таблицы будет использовано имя класса. А поля таблицы будут созданы в соответствии с полями класса.

Аннотацией PrimaryKey мы помечаем поле, которое будет ключом в таблице.

В следующих уроках мы рассмотрим возможности Entity более подробно.

В объекте Dao мы будем описывать методы для работы с базой данных. Нам нужны будут методы для получения списка сотрудников и для добавления/изменения/удаления сотрудников.

Описываем их в интерфейсе с аннотацией Dao.

Методы getAll и getById позволяют получить полный список сотрудников или конкретного сотрудника по id. В аннотации Query нам необходимо прописать соответствующие SQL-запросы, которые будут использованы для получения данных.

Обратите внимание, что в качестве имени таблицы мы используем employee. Напомню, что имя таблицы равно имени Entity класса, т.е. Employee, но в SQLite не важен регистр в именах таблиц, поэтому можем писать employee.

Для вставки/обновления/удаления используются методы insert/update/delete с соответствующими аннотациями. Тут никакие запросы указывать не нужно. Названия методов могут быть любыми. Главное — аннотации.

В следующих уроках мы рассмотрим возможности Dao и его аннотаций более подробно.

Database

Аннотацией Database помечаем основной класс по работе с базой данных. Этот класс должен быть абстрактным и наследовать RoomDatabase.

В параметрах аннотации Database указываем, какие Entity будут использоваться, и версию базы. Для каждого Entity класса из списка entities будет создана таблица.

В Database классе необходимо описать абстрактные методы для получения Dao объектов, которые вам понадобятся.

Практика

Все необходимые для работы объекты созданы. Давайте посмотрим, как использовать их для работы с базой данных.

Database объект — это стартовая точка. Его создание выглядит так:

Используем Application Context, а также указываем AppDatabase класс и имя файла для базы.

Учитывайте, что при вызове этого кода Room каждый раз будет создавать новый экземпляр AppDatabase. Эти экземпляры очень тяжелые и рекомендуется использовать один экземпляр для всех ваших операций. Поэтому вам необходимо позаботиться о синглтоне для этого объекта. Это можно сделать с помощью Dagger, например.

Если вы не используете Dagger (или другой DI механизм), то можно использовать Application класс для создания и хранения AppDatabase:

Не забудьте добавить App класс в манифест

В коде получение базы будет выглядеть так:

Читайте также:  Андроид студио переход между активити

Из Database объекта получаем Dao.

Теперь мы можем работать с Employee объектами. Но эти операции должны выполняться не в UI потоке. Иначе мы получим Exception.

Добавление нового сотрудника в базу будет выглядеть так:

Метод getAll вернет нам всех сотрудников в List

Получение сотрудника по id:

Обновление данных по сотруднику.

Room будет искать в таблице запись по ключевому полю, т.е. по id. Если в объекте employee не заполнено поле id, то по умолчанию в нашем примере оно будет равно нулю и Room просто не найдет такого сотрудника (если, конечно, у вас нет записи с >

Аналогично обновлению, Room будет искать запись по ключевому полю, т.е. по id

Давайте для примера добавим еще один тип объекта — Car.

Описываем Entity объект

Теперь Dao для работы с Car объектом

Будем считать, что нам надо только читать все записи, добавлять новые и удалять старые.

В Database необходимо добавить Car в список entities и новый метод для получения CarDao

Т.к. мы добавили новую таблицу, изменилась структура базы данных. И нам необходимо поднять версию базы данных до 2. Но об этом мы подробно поговорим в Уроке 12. А пока можно оставить версию равной 1, удалить старую версию приложения и поставить новую.

UI поток

Повторюсь, операции по работе с базой данных — синхронные, и должны выполняться не в UI потоке.

В случае с Query операциями мы можем сделать их асинхронными используя LiveData или RxJava. Об этом еще поговорим в следующих уроках.

В случае insert/update/delete вы можете обернуть эти методы в асинхронный RxJava. В моем блоге есть статья на эту тему.

Также, вы можете использовать allowMainThreadQueries в билдере создания AppDatabase

В этом случае вы не будете получать Exception при работе в UI потоке. Но вы должны понимать, что это плохая практика, и может добавить ощутимых тормозов вашему приложению.

Переход на Room

Если вы надумали с SQLite мигрировать на Room, то вот пара полезных ссылок по этой теме:

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

7 шагов к использованию Room. Пошаговое руководство по миграции приложения на Room

Room — это библиотека, которая является частью архитектурных компонентов Android. Она облегчает работу с объектами SQLiteDatabase в приложении, уменьшая объём стандартного кода и проверяя SQL-запросы во время компиляции.

У вас уже есть Android-проект, который использует SQLite для хранения данных? Если это так, то вы можете мигрировать его на Room. Давайте посмотрим, как взять уже существующий проект и отрефакторить его для использования Room за 7 простых шагов.

TL;DR: обновите зависимости gradle, создайте свои сущности, DAO и базу данных, замените вызовы SQLiteDatabase вызовами методов DAO, протестируйте всё, что вы создали или изменили, и удалите неиспользуемые классы. Вот и всё!

В нашем примере приложения для миграции мы работаем с объектами типа User . Мы использовали product flavors для демонстрации различных реализаций уровня данных:

  1. sqlite — использует SQLiteOpenHelper и традиционные интерфейсы SQLite.
  2. room — заменяет реализацию на Room и обеспечивает миграцию.

Каждый вариант использует один и тот же слой пользовательского интерфейса, который работает с классом UserRepository благодаря паттерну MVP.

В варианте sqlite вы увидите много кода, который часто дублируется и использует базу данных в классах UsersDbHelper и LocalUserDataSource . Запросы строятся с помощью ContentValues , а данные, возвращаемые объектами Cursor , читаются столбец за столбцом. Весь этот код способствует появлению неявных ошибок. Например, можно пропустить добавление столбца в запрос или неправильно собрать объект из базы данных.

Давайте посмотрим, как Room улучшит наш код. Изначально мы просто копируем классы из варианта sqlite и постепенно будем изменять их.

Шаг 1. Обновление зависимостей gradle

Зависимости для Room доступны через новый Google Maven-репозиторий. Просто добавьте его в список репозиториев в вашем основном файле build.gradle :

Определите версию библиотеки Room в том же файле. Пока она находится в альфа-версии, но следите за обновлениями версий на страницах для разработчиков:

В вашем файле app/build.gradle добавьте зависимости для Room:

Чтобы мигрировать на Room, нам нужно увеличить версию базы данных, а для сохранения пользовательских данных нам потребуется реализовать класс Migration. Чтобы протестировать миграцию, нам нужно экспортировать схему. Для этого добавьте следующий код в файл app/build.gradle :

Шаг 2. Обновление классов модели до сущностей

Room создаёт таблицу для каждого класса, помеченного @Entity. Поля в классе соответствуют столбцам в таблице. Следовательно, классы сущностей, как правило, представляют собой небольшие классы моделей, которые не содержат никакой логики. Наш класс User представляет модель для данных в базе данных. Итак, давайте обновим его, чтобы сообщить Room, что он должен создать таблицу на основе этого класса:

  • Аннотируйте класс с помощью @Entity и используйте свойство tableName , чтобы задать имя таблицы.
  • Задайте первичный ключ, добавив аннотацию @PrimaryKey в правильные поля — в нашем случае это идентификатор пользователя.
  • Задайте имя столбцов для полей класса, используя аннотацию @ColumnInfo(name = «column_name») . Этот шаг можно пропустить, если ваши поля уже названы так, как следует назвать столбец.
  • Если в классе несколько конструкторов, добавьте аннотацию @Ignore , чтобы указать Room, какой следует использовать, а какой — нет.
Читайте также:  Прошивки андроид через комп

Примечание: для плавной миграции обратите пристальное внимание на имена таблиц и столбцов в исходной реализации и убедитесь, что вы правильно устанавливаете их в аннотациях @Entity и @ColumnInfo .

Шаг 3. Создание объектов доступа к данным (DAO)

DAO отвечают за определение методов доступа к базе данных. В первоначальной реализации нашего проекта на SQLite все запросы к базе данных выполнялись в классе LocalUserDataSource , где мы работали с объектами Cursor . В Room нам не нужен весь код, связанный с курсором, и мы можем просто определять наши запросы, используя аннотации в классе UserDao .

Например, при запросе всех пользователей из базы данных Room выполняет всю «тяжелую работу», и нам нужно только написать:

Шаг 4. Создание базы данных

Мы уже определили нашу таблицу Users и соответствующие ей запросы, но мы ещё не создали базу данных, которая объединит все эти составляющие Room. Для этого нам нужно определить абстрактный класс, который расширяет RoomDatabase . Этот класс помечен @Database , в нём перечислены объекты, содержащиеся в базе данных, и DAO, которые обращаются к ним. Версия базы данных должна быть увеличена на 1 в сравнении с первоначальным значением, поэтому в нашем случае это будет 2.

Поскольку мы хотим сохранить пользовательские данные, нам нужно реализовать класс Migration , сообщающий Room, что он должен делать при переходе с версии 1 на 2. В нашем случае, поскольку схема базы данных не изменилась, мы просто предоставим пустую реализацию:

Создайте объект базы данных в классе UsersDatabase , определив имя базы данных и миграцию:

Чтобы узнать больше о том, как реализовать миграцию баз данных и как они работают под капотом, посмотрите этот пост.

Шаг 5. Обновление репозитория для использования Room

Мы создали нашу базу данных, нашу таблицу пользователей и запросы, так что теперь пришло время их использовать. На этом этапе мы обновим класс LocalUserDataSource для использования методов UserDao . Для этого мы сначала обновим конструктор: удалим Context и добавим UserDao . Конечно, любой класс, который создаёт экземпляр LocalUserDataSource , также должен быть обновлен.

Далее мы обновим методы LocalUserDataSource , которые делают запросы с помощью вызова методов UserDao . Например, метод, который запрашивает всех пользователей, теперь выглядит так:

А теперь время запустить то, что у нас получилось.

Одна из лучших функций Room — это то, что если вы выполняете операции с базой данных в главном потоке, то ваше приложение упадёт со следующим сообщением об ошибке:

Один надёжный способ переместить операции ввода-вывода из основного потока — это создать новый Runnable , который будет создавать новый поток для каждого запроса к базе данных. Поскольку мы уже используем этот подход в варианте sqlite, никаких изменений не потребовалось.

Шаг 6. Тестирование на устройстве

Мы создали новые классы — UserDao и UsersDatabase и изменили наш LocalUserDataSource для использования базы данных Room. Теперь нам нужно их протестировать.

Тестирование UserDao

Чтобы протестировать UserDao , нам нужно создать тестовый класс AndroidJUnit4 . Потрясающая особенность Room — это возможность создавать базу данных в памяти. Это исключает необходимость очистки после каждого теста.

Нам также нужно убедиться, что мы закрываем соединение с базой данных после каждого теста.

Например, чтобы протестировать вход пользователя, мы добавим пользователя, а затем проверим, сможем ли мы получить этого пользователя из базы данных.

Тестирование использования UserDao в LocalUserDataSource

Убедиться, что LocalUserDataSource по-прежнему работает правильно, легко, поскольку у нас уже есть тесты, которые описывают поведение этого класса. Всё, что нам нужно сделать, это создать базу данных в памяти, получить из нее объект UserDao и использовать его в качестве параметра для конструктора LocalUserDataSource .

Опять же, нам нужно убедиться, что мы закрываем базу данных после каждого теста.

Тестирование миграции базы данных

Подробнее почитать о том, как реализовать тесты миграции баз данных, а также, как работает MigrationTestHelper , можно в этом посте.

Вы также можете посмотреть код из более детального примера приложения миграции.

Шаг 7. Удаление всего ненужного

Удалите все неиспользуемые классы и строки кода, которые теперь заменены функциональностью Room. В нашем проекте нам просто нужно удалить класс UsersDbHelper , который расширял класс SQLiteOpenHelper .

Если у вас есть большая и более сложная база данных, и вы хотите постепенно перейти на Room, то рекомендуем этот пост.

Теперь количество стандартного кода, подверженного ошибкам, уменьшилось, запросы проверяются во время компиляции, и всё тестируется. За 7 простых шагов мы смогли мигрировать наше существующее приложение на Room. Пример приложения можете посмотреть здесь.

Источник

Оцените статью