- Правильная работа с БД в Android
- Room: Хранение данных на Android для всех и каждого
- Использование Room
- Преимущества использования Room
- Самое большое ограничение в Room: взаимосвязи
- Стоит ли использовать Room?
- How to Save Data to the Firebase Realtime Database in Android?
- What is Firebase Realtime Database?
- What are the Advantages of using the Firebase Realtime Database?
- What We are Going to Build in This Article?
- Step by Step Implementation
Правильная работа с БД в Android
Приветствую всех дроидеров в эти непростые для нас времена.
Честно говоря, заколебала эта шумиха о патентах, войнах и т.д., но в данной статье речь пойдет не об этом.
Я не собирался писать статью на данную тему, так как везде всего полно о работе с базой данных в Android и вроде бы все просто, но уж очень надоело получать репорты об ошибках, ошибках специфичных и связанных с БД.
Поэтому, я рассматрю пару моментов с которыми я столкнулся на практике, чтобы предостеречь людей, которым только предстоит с этим разбираться, а дальше жду ваших комментариев на тему решения указанных проблем после чего внесу изменения в пост и мы сделаем отличный туториал, который будет образцом работы с SQLite в Android не только для начинающих, но и для тех, кто уже знаком с основами и написал простые приложения.
Способы работы с БД
Существует три способа работы с данными в БД, которые сразу бросаются на ум:
1) Вы создаете пустую структуру базы данных. Пользователь работает с приложением(создает заметки, удаляет их) и база данных наполняется. Примером может служить приложение NotePad в демо-примерах developer.android.com или на вашем дроид-девайсе.
2) Вы уже имеете готовую БД, наполненную данными, которую нужно распространять с приложением, либо парсите данные из файла в assets.
3) Получать данные из сети, по мере необходимости.
Если есть какой-то еще один или два способа, то с радостью дополню данный список с вашей помощью.
Все основные туториалы расчитаны как раз на первый случай. Вы пишите запрос на создание структуры БД и выполняете этот запрос в методе onCreate() класса SQLiteOpenHelper, например так:
Примерно так. Более полный вариант класса и других составляющих можно посмотреть по ссылке внизу статьи.
Дополнительно можно переопределить методы onOpen(), getReadableDatabase()/getWritableDatаbase(), но обычно хватает того, что выше и методов выборки данных.
Далее, экземпляр этого класса создаем в нашем приложении при его запуске и выполняем запросы, то бишь проблемная часть пройдена. Почему она проблемная? Потому что, когда пользователь качает приложения с маркета, то не задумывается о вашей базе данных и может произойти что угодно. Скажем сеть пропала или процесс другой запустился, или вы написали уязвимый к ошибкам код.
Кстати, есть еще один момент, на который стоит обратить внимание. Переменную экземпляра нашего класса можно создать и хранить в объекте Application и обращаться по мере необходимости, но нужно не забывать вызывать метод close(), так как постоянный коннект к базе — это тяжелый ресурс. Кроме того могут быть коллизии при работе с базой из нескольких потоков.
Но есть и другой способ, например, создавать наш объект по мере необходимости обращения к БД. Думаю это вопрос предпочтения, но который также необходимо обсудить.
А теперь самое главное. Что, если нам понадобилось использовать уже сушествующую БД с данными в приложении?
Немного погуглив, Вы сразу наткнетесь на такую «замечательную статью» — www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications в которой, как покажется, есть нужная панацея. Но не тут то было. В ней еще и ошибок несколько.
Вот они:
1) В методе createDataBase() строка:
SQLiteDatabase dbRead = getReadableDatabase();
и далее код… содержит crash приложения на НТС Desire, потому что получаем БД для чтения(она создается), но не закрывается.
Добавляем строкой ниже dbRead.close() и фикс готов, но момент спорный.
Вот что говорит дока на тему метода getReadableDatabase():
Create and/or open a database. This will be the same object returned by getWritableDatabase() unless some problem, such as a full disk, requires the database to be opened read-only. In that case, a read-only database object will be returned. If the problem is fixed, a future call to getWritableDatabase() may succeed, in which case the read-only database object will be closed and the read/write object will be returned in the future.
Like getWritableDatabase(), this method may take a long time to return, so you should not call it from the application main thread, including from ContentProvider.onCreate().
И так. Данный метод не стоит вызывать в главном потоке приложения. В остальном все понятно.
2) Ошибка: No such table android_metadata. Автор поста выкрутился, создав данную таблицу заранее в БД. Не знаю на сколько это правильный способ, но данная таблица создается в каждой sqlite-бд системой и содержит текущую локаль.
3) Ошибка: Unable to open database file. Здесь много мнений, разных мнений, которые Вы можете прочесть по ссылкам ниже.
Возможно, что проблемы связаны с тем, что один поток блокирует БД и второй не может к ней обратиться, возможно проблема в правах доступа к приложению(было замечено, что чаще проблемы с БД проявляются на телефонах марки НТС именно на тех моделях, которые нельзя рутануть, хотя не только на них, например на планшетах Асер), но как бы то ни было проблемы эти есть.
Я склоняюсь к варианту, что проблема в потоках, не зря ведь нам не рекомендуют вызывать методы создания базы в главном потоке.
Возможно выходом из этого будет следующее решение(рассматривается вариант №2). Используя первый вариант работы с базой, наполнить ее данными после создания, например:
Данный подход еще нужно проверить на практике, но так как этот пост нацелен на выработку верного коллективного решения по данной тематике, то комментарии и пробы на даннную тему только приветствуются.
Мораль истории такова: если вы нашли какой-то хороший кусок кода для вашего решения, то проверьте его, не поленитесь, прежде чем копипастить в свой проект.
Вцелом, данный пост показывает(касательно способа №2) как делать не надо, но и также содержит пару любопытных мыслей.
Метод getReadableDatabase() можно переопределить например так:
Кстати: следуя практике самой платформы, поле первичного ключа стоит называть «_id».
Пишите в комментарии свои используемые практики. Мы сделаем данный пост лучше для всех, а может и мир станет чуточку добрее.
UPD Только что проверил свой подход. Все работает в эмуляторе, но будьте осторожны.
Файлик data.txt лежит в assets такой:
Zametka #1
Zametka #2
Zametka #3
Zametka #4
И класс приложения:
Отмечу, что данный класс используется только для демонстрации и проверки того, что произойдет при вызове методов getReadableDatabase()/getWritableDatabase() и создании базы. В реальных проектах код нужно адаптировать.
Кроме того в базе появилась табличка android_metadata(без моего участия), поэтому указанная выше ошибка решена.
Надеюсь кому-то пригодится.
Любопытные дополнения №1(от хабраюзера Kalobok)
Источник
Room: Хранение данных на Android для всех и каждого
Room — это новый способ сохранить данные приложений в Android-приложении, представленный в этом году на Google I/O. Это часть новойAndroid Architecture, группа библиотек от Google, которые поддерживают уместную архитектуру приложений. Room предлагается в качестве альтернативы Realm, ORMLite, GreenDao и многим другим.
Room — это высокоуровневый интерфейс для низкоуровневых привязок SQLite, встроенных в Android, о которых вы можете узнать больше в документации. Он выполняет большую часть своей работы во время компиляции, создавая API-интерфейс поверх встроенного SQLite API, поэтому вам не нужно работать с Cursor или ContentResolver.
Использование Room
Во-первых, добавьте Room в свой проект. После этого вам нужно будет передать в Room, как выглядят ваши данные. Предположим, имеется простой класс модели, который выглядит следующим образом:
Чтобы рассказать Room о классе Person, добавляем аннотицию Entity к классу и @PrimaryKey к ключу:
Благодаря этим двум аннотациям Room теперь знает, как создать таблицу для хранения экземпляров Person.
Важная вещь, которую следует учитывать при настройке ваших моделей: каждое поле, которое хранится в базе данных, должно быть общедоступным или иметь геттер и сеттер в стандартном стиле Java Beans (например, getName () и setName (имя строки)).
В классе Person теперь есть вся информация, которая требуется Room для создания таблиц, но у вас нет способа фактически добавлять, запрашивать или удалять данные из базы данных. Вот почему вам нужно будет сделать объект доступа к данным (DAO). DAO предоставляет интерфейс в самой базе данных и занимается манипулированием хранимыми данными Person.
Вот простой интерфейс DAO для класса Person:
Первое, что нужно заметить, это то, что PersonDao — это интерфейс, а не класс. Другая интересная деталь — это инструкции SQL в аннотациях Query (). Операторы SQL говорят Room, какую информацию вы хотите получить из базы данных. Они также проверяются во время компиляции. Поэтому, если вы измените подпись метода List getAllPeopleWithFavoriteColor ( название цвета ) на List getAllPeopleWithFavoriteColor ( int color ), Room выдаст ошибку во время компиляции:
И если вы сделаете опечатку в выражении SQL, например, напишите favoriteColors ( множественное число ) вместо favoriteColor ( единственное число ), Room также выдаст ошибку компиляции:
Вы не можете получить экземпляр PersonDao, потому что это интерфейс. Чтобы иметь возможность использовать классы DAO, вам необходимо создать класс базы данных. За кулисами этот класс будет отвечать за ведение самой базы данных и предоставление экземпляров DAO.
Вы можете создать свой класс базы данных всего за пару строк:
Это лишь описание структуры базы данных, но сама база данных будет жить в одном файле. Чтобы получить экземпляр AppDatabase, сохраненный в файле с именем populus-database, вы должны написать:
Если вы хотите получить все данные обо всех Person, которые находятся в базе данных, вы могли бы написать:
Преимущества использования Room
В отличие от большинства ORM, Room использует обработчик аннотации для выполнения всей своей манеры сохранения данных. Это означает, что ни ваши классы приложений, ни классы моделей не должны ничего расширять в Room, в отличие от многих других ORM, включая Realm и SugarORM. Как вы видели при ошибках с аннотациями Query () выше, вы также получаете возможность проверки корректности SQL-запросов во время компиляции, что может сэкономить вам много хлопот.
Room также позволяет вам наблюдать за изменениями данных, интегрируя их как с API LiveData Архитектурных Компонентов, так и с RxJava 2. Это означает, что если у вас сложная схема, где изменения в базе данных должны появляться в нескольких местах вашего приложения, Room делает уведомления об изменениях. Это мощное дополнение может быть включено одной строкой. Все, что вам нужно сделать, это изменить тип возвращаемых значений.
Например, этот метод:
Самое большое ограничение в Room: взаимосвязи
Самым большим ограничением в Room является то, что он не будет обрабатывать отношения с другими типами сущностей для вас автоматически, как и другие ORM. Это означает, что если вы хотите отслеживать домашних животных:
То Room выдаст ошибку компиляци, так как не знает, как сохранить отношения между Person и Pet:
Ошибка при компиляции предлагает конвертер типов, который преобразует объекты в примитивы, которые могут быть непосредственно сохранены в SQL. Поскольку List нельзя свести к примитиву, вам нужно сделать что-то другое. Это отношения «один ко многим», где у одного Person может быть много Pet. Room не может моделировать такие отношения, но она может справиться с обратными отношениями — у каждого Pet есть один Person. Чтобы смоделировать это, удалите поле для Pet в Person и добавьте поле ownerId в класс Pet:
Это приведет к тому, что Room обеспечит ограничение внешнего ключа между объектами. Room не будет вызывать отношения «один-ко-многим» и «много-к-одному», но она дает вам инструменты для выражения этих отношений.
Чтобы получить всех домашних животных, принадлежащих конкретному человеку, вы можете использовать запрос, который находит всех домашних животных с данным идентификатором владельца. Например, вы можете добавить в свой DAO следующий метод:
Стоит ли использовать Room?
Если вы уже настроили сохранение данных в своем приложении и довольны им, то ничего не изменяйте. Каждая ORM и встроенная реализация SQLite будут продолжать работать так же, как и раньше. Room — это всего лишь еще один вариант сохранения данных.
Если вы используете SQLite или собираетесь использовать его, вы должны попробовать Room. Он обладает всеми возможностями, необходимыми для выполнения расширенных запросов, одновременно устраняя необходимость писать SQL-запросы для поддержки базы данных самостоятельно.
Источник
How to Save Data to the Firebase Realtime Database in Android?
Firebase is one of the famous backend platforms which is used by so many developers to provide backend support to their applications and websites. It is the product of Google which provides services such as database, storage, user authentication, and many more. In this article, we will create a simple app in which we will be adding our Data to Firebase Realtime Database. Note that we are going to implement this project using the Java language.
What is Firebase Realtime Database?
Firebase Realtime Database is a NoSQL cloud database that is used to store and sync the data. The data from the database can be synced at a time across all the clients such as android, web as well as IOS. The data in the database is stored in the JSON format and it updates in real-time with every connected client.
What are the Advantages of using the Firebase Realtime Database?
- The main advantage of using the Firebase Realtime database is that the data is updated in a real-time manner and you don’t have to make any requests for the data updates or changes. The database uses data synchronization every time when data changes and these changes will reflect the connected user within milliseconds.
- While using Firebase Realtime Database your apps remain responsive even if the device loses its connectivity to the database. Once the user has established the connection he will receive the changes made in the data from the database.
- The data stored in the Firebase database can be easily accessible through the web portal of Firebase. You can manage your database from PC as well as mobile devices. You can manage the rules of the database which gives permissions to read and write operations to the database.
What We are Going to Build in This Article?
In this article, we are going to build a simple application in which we will be getting the data from the users with the help of some TextFields and store that data in the Firebase Realtime Database. Note that we are using Firebase Realtime Database and the app is written using JAVA language.
Step by Step Implementation
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.
Step 2: Connect your app to Firebase
After creating a new project navigate to the Tools option on the top bar. Inside that click on Firebase. After clicking on Firebase, you can get to see the right column mentioned below in the screenshot.
Inside that column Navigate to Firebase Realtime Database. Click on that option and you will get to see two options on Connect app to Firebase and Add Firebase Realtime Database to your app. Click on Connect now and your app will be connected to Firebase. After that click on the second option and now your App is connected to Firebase.
After connecting your app to Firebase you will get to see the below screen.
After that verify that dependency for Firebase Realtime database has been added to our Gradle file. Now navigate to the app > Gradle Scripts and inside that file check whether the below dependency is added or not. If the below dependency is not added in your build.gradle file. Add the below dependency in the dependencies section.
After adding this dependency sync your project and now we are ready for creating our app. If you want to know more about connecting your app to Firebase. Refer to this article to get in detail about Adding Firebase to Android App.
Источник