Androidstudio — SQLite в Android Studio НУЖНА ПОМОЩЬ


Содержание

Программирование SQL базы данных в Android

По умолчанию в Android используется база данных SQLite — это довольно популярная, легкая и быстрая реляционная база данных. Если для вас SQL – это пустой звук, то, скорее всего, вы мало что поймете из этой статьи. Предполагается, что читатель знаком с SQL, знает что такое запросы выборки, триггеры и представления. Если это не так — почитайте какое-нибудь введение в SQL, а потом возвращайтесь сюда.

База данных SQLite имеет некоторые особенности, о которых нужно помнить:

  • Не поддерживается проверка типов данных. Это значит, что Вы случайно сможете записать данные не того типа, например поместить строку в колонку, предназначенную для целых чисел.
  • Не поддерживается ссылочная целостность: нет поддержки FOREIGN KEY и конструкций JOIN.
  • Полная поддержка Unicode отключена по умолчанию.

Давайте создадим простую базу данных, содержащую информацию о работниках. База содержит две таблицы: Employees — для хранения данных о сотрудниках и Dept — о департаментах. И представление ViewEmps, связывающее работников с департаментами.

Создание SQLite базы данных в Android проекте

По умолчанию, Android не содержит удобных СУБД для создания и работы с базами данных (есть sqlite3.exe — консоль для работы с базой данных), поэтому давайте создадим базу и все необходимые таблицы непосредственно из кода.

Во-первых, мы напишем класс, который будет управлять всеми операциями с базой данных: созданием базы, созданием таблиц, вставкой и удалением записей. Давайте создадим класс потомок отSQLiteOpenHelper. Нам нужно переопределить два метода:

  • onCreate(SQLiteDatabase db) — вызывается при создании базы данных. Здесь мы можем создать таблицы, определить в них колонки, создать виды и триггеры.
  • onUpgrade(SQLiteDatabse db, int oldVersion, int newVersion) — вызывается, при внесении изменений в базу, например при создании и удалении таблиц

Внутри нашего класса определим переменные

Как видите, здесь мы просто вызываем конструктор суперкласса, который имеет четыре параметра:

  • Context— контекст, связанный с базой данных.
  • dataBaseName— имя базы данных.
  • CursorFactory— можно использовать класс, созданный на основе класса Cursor. Это позволяет проводить некоторые дополнительные проверки и операции с результатами запросов. Если сюда подставить ссылку на наш класс, он будет использоваться вместо стандартного курсора. Мы не будем работать с CursorFactory, поэтому передадим значение null.
  • Version— версия базы данных. Смысл этого параметра будет раскрыт ниже

Создание базы данных

Давайте переопределим методonCreate

Внутри метода мы с помощью SQL запросов создаем таблицы, триггеры и представления. Запросы вызываются для базы db с помощью методаexecSQL.

МетодonCreate вызывается при создании базы данных, как только база создана, мы добавляем туда таблицы с необходимым набором полей. Вызов метода происходит, когда база данных не существует на диске, то есть для данного конкретного устройства этот метод будет вызван всего один раз, сколько бы мы потом не запускали нашу программу.

Изменение базы данных

Иногда возникает необходимость внести изменения в базу данных: поменять схему, добавить новые таблицы или поменять типы столбцов таблиц. Все это можно сделать внутри методаonUpdate(SQLiteDatabase db,int old Version,int newVerison) .

Этот метод вызывается, когда изменяется номер, указанный в конструкторе класса. Помните то загадочное число 33, внутри конструктораDatabaseHelper? Если Вам вдруг понадобится внести изменение в свою базу, просто поменяйте номер в конструкторе. То есть, если вы измените конструктор

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

Управление внешними ключами

Давайте создадим триггер, который будет следить при добавлении нового сотрудника за тем, чтобы указанный в описании сотрудника департамент присутствовал в таблице Dept.

SQL команда, создающая такой триггер, выглядит следующим образом:

Выполнение SQL команд в Android

Как уже было отмечено выше, Вы можете выполнить любую SQL команду с помощью мtтодаdb.execSQL(String statement).

Добавление записи в таблицу

Можно добавить новую запись в таблицу с помощью SQL командыINSERT, а можно воспользоваться методомdb.insert:

Обратите внимание, для соединения с базой данных мы вызвали методthis.getWritableDatabase(). КлассContentValuesпозволяет создать карту с параметрами ключ-значение. Эта карта затем используется методомinsert, который фактически добавляет запись в таблицу. МетодContentValues.put создает пару ключ-значение. Еще одно замечание, хорошим тоном считается закрывать базу данных вызовом метода close() после завершения выполнения группы команд.

Изменение значений в таблице

Изменить значение в какой-либо записи можно с помощью SQL командыUPDATEили с помощью метода db.update:

Метод update имеет следующие параметры:

  • String Table: название таблицы в которой мы хотим что-то изменить.
  • ContentValues cv: пара ключ-значение с новой информацией.
  • String where: строка-шаблон, определяющая условие WHERE, которое проверяется для каждой строки таблицы. Ксли условие истинно, то в этой строке обновляется информация в соответствии с параметром cv.
  • String[] args: массив с аргументами, которые подставляются в строку-шаблон where.

Удаление строк

Удалить строку в таблице можно с помощью SQL командыDELETE, а также с помощью методаdb.delete. Этот метод имеет аналогичный updateнабор параметров (за исключением cv).

Выполнение SQL запросов

Для выполнения запросов в Android используются два метода:db.rawQuery иdb.query. Давайте сделаем запрос к базе, с целью получения списка всех департаментов:

МетодrawQuery имеет два параметра:

  • String query: Строка с SQL запросом SELECT.
  • String[] selection args: массив аргументов where, если он используется в SELECT запросе.

Замечания! В качестве результата этого запроса возвращается объектCursor. Если в качестве ключевого поля в таблице используется колонка с именем, отличным от _id, Вам необходимо использовать alias в форме «SELECT [Column Name] as _id». Дело в том, что объектCursorвсегда считает, что ключевое поле имеет имя_id, и если это не так, генерируется исключение.

Другим способом выполнения запроса к базе является вызов методаdb.query. Давайте напишем метод, который выдает всех сотрудников, работающих в каком-то конкретном департаменте:

Методdb.query имеет следующий набор параметров:

  • String Table Name: Имя таблицы, из которой осуществляется выборка.
  • String [ ] columns: список столбцов, которые войдут в результат.
  • String WHERE clause: шаблон where-условия или null.
  • String [ ] selection args: массив с аргументами where-условия.
  • String Group by: условие группировки.
  • String Having: условие HAVING.
  • String Order By by: порядок сортировки.

Управление объектом Cursor

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

  • boolean moveToNext()— перемещает указатель на одну запись вперед. Возвращает false, если достигнут конец таблицы результата.
  • boolean moveToFirst()— перемещает указатель на первую строку. Возвращает false, если таблица-результат не содержит строк.
  • boolean moveToPosition(int position) — перемещает указатель на конкретную строку в таблице результатов. Если строки с таким номером нет — возвращает false.
  • boolean moveToPrevious()— перемещает указатель на одну запись назад. Возвращает false, если достигнуто начало таблицы результата.
  • boolean moveToLast()— перемещает указатель на последнюю строку. Возвращает false, если таблица-результат не содержит строк.
  • int getColumnIndex(String column)— возвращает ссылку на колонку column в текущей строке. Для получения значения по ссылке используются методыCursor.getInt(int ColumnIndex), getShort,getString,getDouble, getBlob.

Для определение текущей позиции указателя можно воспользоваться методами: boolean isAfterLast(), isBeforeFirst, isFirst, isLast и isNull(columnIndex). Их назначение без труда можно понять из названий.

Если в результате выполнения запроса вы получили только одну строку, то извлечь из нее значения столбцов можно следующим образом:

В результате выполнения этого метода, мы получим значение колонки _id текущей строки. После использования курсора его хорошо бы закрыть с помощью методаclose().

Вот собственно и все. Теперь вы вполне сможете использовать базы данных в своих Android проектах.

Создаём приложение заметок. Основы работы с SQLite в Andro >

В прошлых уроках мы создали своё первое серьёзное приложение, позволяющее устанавливать и удалять приложения.

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

Давайте же сформулируем задачу, которую мы решим за ближайшие несколько уроков: создать приложение, которое позволит создавать, хранить, удалять и редактировать заметки. Приложение должно уметь не только сохранять текст (это слишком уж банально), но и прикреплять фотографии.

Ну и, конечно же, всё это будет реализовано с использованием Material Design.

Работа с SQLite

В Android, как и в iOS, есть встроенная в систему компактная база данных — SQLite.

SQLite обладает рядом недостатков — например, в него нельзя писать данные одновременно из нескольких потоков. Однако, все эти недостатки перекрываются огромным (для мобильных устройств) преимуществом: она чрезвычайно компактна.

Вся база данных хранится в одном-единственном файле, и, хоть и работает она относительно медленно (по сравнению со «старшими братьями»; для своих целей она является очень даже шустрой), но при этом занимает очень мало места и способна работать даже на самых слабых устройствах.

Чтобы понять, как оно работает, давайте попробуем поработать с SQLite на компьютере. Если вы не знакомы с SQL, рекомендую ознакомиться с этой статьёй и ссылками в ней.

В практике работы с SQLite нам поможет приложение SQLite Database Browser. Оно полностью бесплатно, работает на macOS, Windows и Linux, и исходный код доступен на GitHub. Скачайте и установите его.

После установки запустите приложение и нажмите на кнопку New Database:

Кнопка «New Database»

Введите имя и расположения файла, в котором будет создана БД и нажмите на кнопку Save:

Выбор файла для сохранения БД

После этого появится диалог, предлагающий создать таблицу. Закройте его — мы будем создавать её вручную.

Выберите вкладку Execute SQL:

Вкладка «Execute SQL»

Для начала нам нужна одна таблица, в которой мы будем хранить заметки. В таблице будут такие столбцы:

  • id — integer , primary key . Идентификатор заметки.
  • title — text , заголовок заметки.
  • note — text , текст заметки.
  • created_ts — integer , дата создания заметки в формате unix time.
  • updated_ts — integer , дата последнего изменения заметки в формате unix time.
Цукерберг рекомендует:  Как легко сделать из таблицы зебру

SQL-запрос для создания таблицы будет таким:

Введите его в поле для запроса и нажмите на кнопку Execute SQL. Результат выполнения появится в окне ниже:

Результат выполнения SQL


Теперь вернемся на вкладку Database Structure и посмотрим, что получилось:

Структура БД SQLite

Отлично. Теперь вставим первую заметку в нашу таблицу:

В качестве времени создания и обновления для простоты передадим 0 , то есть начало эпохи UNIX. Выполните этот запрос и перейдите на вкладку Browse Data:

Данные в БД SQLite

Как видите, данные вставились успешно. Добавьте ещё одну заметку:

У неё мы изменили время создания и редактирования.

Зачем? Чтобы показать работу сортировки в SQLite. Мы будем показывать первыми те заметки, которые были изменены последними.

Если вы выполните следующий запрос:

То получите вот такой результат:

Результат выполнения SELECT

То есть первой показывается первая заметка. А теперь выполните вот такой запрос:

В нём мы говорим базе данных, что нужно отсортировать данные по полю updated_ts , при этом сортировку нужно выполнить по убыванию. Результатом будет следующий набор данных:

Данные в БД SQLite с сортировкой

Теперь давайте попробуем обновить заметку:

Главное — не забыть WHERE , иначе обновятся все строки в таблице.

Ну и удалим заметку:

Последняя вещь, о которой нужно узнать — это индексы. Если у пользователя будет много заметок, то сортировка может занимать достаточно продолжительное время, в результате, список заметок будет отображаться с лагами. Поэтому нам нужно создать индекс по столбцу updated_ts :

Вот и всё! Примерно то же самое мы будем делать в нашем приложении.

SQLite в Android

Работа с SQLite в Android отличается от того, что мы делали ранее всего парой аспектов:

  • Вам почти никогда не придётся работать с «сырыми» SQL-запросами — для вставки/получения/удаления записей есть удобные методы.
  • Стандартное для большинства движков БД имя столбца id в Android по какой-то неведомой причине принято заменять на _id . Лучше следовать этому стандарту, иначе некоторые вещи могут сломаться.

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

Создайте новый проект, как мы делали это ранее. В прошлом проекте мы хранили все файлы в одном пакете. В этом мы более аккуратно подойдём к организации. Начнём, собственно, с БД.

Внутри основного пакета создайте пакет db :

Создание нового пакета

Контракт БД

В пакете db , который мы создали ранее, создайте класс NotesContract :

Этот класс облегчит работу с БД, а так же будет выступать в качестве «документации» структуры нашей БД для тех, кто возможно будет смотреть наши исходники. В нём мы будем описывать таблицы, которые будут присутствовать в БД.

Создание расписания уроков для андроид устройств. Часть 2. База данных SQLITE и фрагменты

В этом уроке продолжим модифицировать наше приложение Расписания уроков для андроид устройств, и изменим принцип загрузки данных во фрагменты.

В предыдущей версии информация поступала из строковых массивов, которые были созданы в файле String.xml, посредником между данными и приложением являлся Array Adapter, а сегодня сделаем загрузку из базы данных SQLite.

Она будет находиться в apk файле, вместе с самим приложением, так что никаких настроек или манипуляций не нужно будет делать. Установил, открыл — работает.

Кто не читал статью «Создание расписания уроков для андроид устройств. Array Adapter для фрагментов» переходите по ссылке, в ней вы сможете скачать файл проекта, который будем редактировать.

Создание базы данных в Excel

В прошлой статье я не оговорился, сказав, что базу данных будем делать в Excel. Давайте создадим таблицу с расписанием уроков, по классам, дням недели и перечнем занятий.
Для этого в новой книге дадим названия полей таблицы:

  • class — номер класса(11-6)
  • day — день недели(1-5)
  • urok_id- порядок уроков
  • urok — название предмета.

На втором листе книги напишем номер предмета и название, с помощью функции на первом листе в столбец urok введем формулу =СЛУЧМЕЖДУ(1;13) так как на втором листе 13 предметов, а в соседнюю ячейку =ВПР(D2,Лист2!A:B;2;0) для получения списка пердметов.

Использование DB Browser for SQLite

Затем скопируем как значения получившийся список на новый лист и сохраним его как CSV(разделитель — запятые).

Далее нам понадобится программа DB Browser for SQLite (я пользуюсь версией 3.5.1), в которой создадим новую базу данных(New Database), назавем ее 1.sqlite.

Нажмем File->Import->Table from CSV file. укажем путь к сохраненной ранее книге, присвоим название таблице myrasp, поставим галочку Column name in first line, кодировка Other — CP1251, разделитель «;» и нажмем Ok.

Модифицируем таблицу myrasp, нажав ПКМ, добавим новое поле(Add field) «_id» с типом text или integer, отметим галочками PK(первичный ключ) и AI(автоинкремент). Поле «_id» можно поднять выше в списке полей таблицы.

Создание директории assets

Вернемся в Android Studio и создадим папку assets для хранения нашей базы данных SQLite, нажав в проекте ПКМ: New->Folder->Asset Folder. Если вы скопируете 1.sqlite то можно сразу в эту папку вставить файл, я же в Total Comander переименую в rasp.sqlite и скопирую в проект в папку assets. Когда мы перейдем в среду разработки Android Studio, то в папке будет видна наша база.

Изменения не коснутся файлов MainActivity.java и MainActivity11.java, будем использовать код из предыдущего проекта. В файле fragment_main11.java, отвечающем за отображение уроков понедельника уберем конструкцию switch(classId)<> целиком, удалим переменную ListAdapter adapter.

Класс DatabaseHelper.java для работы с базой данных

Создадим новый класс DatabaseHelper.java, он понадобится для связи с базой данных, открытия, чтения данных.

Данный код универсален для любых проектов, в настройках можно менять названия переменных DB_NAME, TABLE, COLUMN_.

Настройки таблицы

Напишем название базы данных и таблицы в переменные

Присвоим поля таблицы myrasp переменным

Хочу обратить ваше внимание на переменную DB_PATH, которую я для упрощения написал просто «/data/data/»+название пакета+»/database/». В моем случае название пакета — ru.maxfad.myraspisanie, у вас может и будет отличаться для других приложений.

Работа с фрагментами

Теперь откроем fragment_main11.java, в который добавим метод onCreateView

Поскольку нам нужно получить доступ к фрагменту из активности напишем функцию, в которой свяжемся со слоем фрагмента fragment_main11.xml, а в переменную mList получим ListView для отображения уроков

Во fragment_main11.xml удалим секцию разметки TextView и переименуем id ListView

Добавим переменные для работы с базой данных

В метод onActivityCreate напишем новый экземпляр класса DatabaseHelper и создадим базу данных

Напишем метод onResume в котором и будет происходить выборка данных из таблицы myrasp, выполняться SQL запрос и формироваться список уроков

Как вы можете обратить внимание, в строке » and day=1″ и заключается принцип загрузки данных по дням недели, в остальных фрагментах код будет отличаться только номером дня.

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

Архив с кодом проекта можно скачать по ссылке ниже, обязательно посмотрите видеоролик по материалам статьи, в нем есть БОНУС: на примере этого приложения я покажу, как работать в Android Studio с макетом с помощью BluePrint+Design.

А на сегодня все, делитесь этой статьей в соцсетях и подписывайтесь на канал YouTube.

Cкачать архив для ознакомления — проект Расписание для уроков:

Создание расписания уроков для андроид устройств. Часть 2. База данных SQLITE и фрагменты + БОНУС :

Рекомендуем смотреть видео в полноэкранном режиме, в настойках качества выбирайте 1080 HD, не забывайте подписываться на канал в YouTube, там Вы найдете много интересного видео, которое выходит достаточно часто. Приятного просмотра!

Работа с базами данных SQLite

Подключение к базе данных SQLite

В Andro >android.database.sqlite определен набор классов, которые позволяют работать с базами данных SQLite. И каждое приложение может создать свою базу данных.

Чтобы использовать SQLite в Android, надо создать базу данных с помощью выражение на языке SQL. После этого база данных будет храниться в каталоге приложения по пути:

ОС Android по умолчанию уже содержит ряд встроенных бад SQLite, которые используются стандартными программами — для списка контактов, для хранения фотографий с камеры, музыкальных альбомов и т.д.

Основную функциональность по работе с базами данных предоставляет пакет android.database . Функциональность непосредственно для работы с SQLite находится в пакете android.database.sqlite .

База данных в SQLite представлена классом android.database.sqlite.SQLiteDatabase . Он позволяет выполнять запросы к бд, выполнять с ней различные манипуляции.

Класс android.database.sqlite.SQLiteCursor предоставляет запрос и позволяет возвращать набор строк, которые соответствуют этому запросу.

Класс android.database.sqlite.SQLiteQueryBuilder позволяет создавать SQL-запросы.

Сами sql-выражения представлены классом android.database.sqlite.SQLiteStatement , которые позволяют с помощью плейсхолдеров вставлять в выражения динамические данные.

Класс android.database.sqlite.SQLiteOpenHelper позволяет создать базу данных со всеми таблицами, если их еще не существует.


В SQLite применяется следующая система типов данных:

INTEGER : представляет целое число, аналог типу int в java

REAL : представляет число с плавающей точкой, аналог float и double в java

TEXT : представляет набор символов, аналог String и char в java

BLOB : представляет массив бинарных данных, например, изображение, аналог типу int в java

Сохраняемые данные должны представлять соответствующие типы в java.

Создание и открытие базы данных

Для создания или открытия новой базы данных из кода Activity в Andro >openOrCreateDatabase() . Этот метод может принимать три параметра:

название для базы данных

числовое значение, которое определяет режим работы (как правило, в виде константы MODE_PRIVATE )

необязательный параметр в виде объекта SQLiteDatabase.CursorFactory , который представляет фабрику создания курсора для работы с бд

Например, создание базы данных app.db :

Для выполнения запроса к базе данных можно использовать метод execSQL класса SQLiteDatabase. В этот метод передается SQL-выражение. Например, создание в базе данных таблицы users:

Если нам надо не просто выполнить выражение, но и получить из бд какие-либо данные, то используется метод rawQuery() . Этот метод в качестве параметра принимает SQL-выражение, а также набор значений для выражения sql. Например, получение всех объектов из базы данных:

Метод db.rawQuery() возвращает объект Cursor, с помощью которого мы можем извлечь полученные данные.

Возможна ситуация, когда в базе данных не будет объектов, и для этого методом query.moveToFirst() пытаемся переместиться к первому объекту, полученному из бд. Если этот метод возвратит значение false, значит запрос не получил никаких данных из бд.

Теперь для работы с базой данных сделаем простейшее приложение. Для этого создадим новый проект.

В файле activity_main.xml определим простейший графический интерфейс:

А в классе MainActivity определим взаимодействие с базой данных:

По нажатию на кнопку здесь вначале создается в базе данных app.db новая таблица users, а затем в нее добавляются два объекта в базу данных с помощью SQL-выражения INSERT.

Далее с помощью выражения SELECT получаем всех добавленных пользователей из базы данных в виде курсора Cursor.

Вызовом query.moveToFirst() перемещаемся в курсоре к первому объекту, и так как у нас может быть больше одного объекта, то проходим по всему курсору в цикле do. while.

Для получения данных из курсора применяются методы query.getString(0) и query.getInt(1) . В скобках в методы передается номер столбца, из которого мы получаем данные. Например, выше мы добавили вначале имя пользователя в виде строки, а затем возраст в виде числа. Значит, нулевым столбцом будет идти строкое значение, которое получаем с помощью метода getString() , а следующим — первым столбцом идет числовое значение, для которого применяется метод getInt() .

После завершения работы с курсором и базой данных мы закрываем все связанные объекты:

Если мы не закроем курсор, то можем столкнуться с проблемой утечки памяти.

И если мы обратимся к приложению, то после нажатия на кнопку в текстовое поле будут выведены добавленные данные:

ИнтеллигенцияX

Как работать с базой данных SQLite в Android Studio

А давай-ка я добавлю Android Studio + SQLite

На форме размещаем три текстовых метки, три поля для ввода/отображения информации из базы, полей ФИО, Должность, Телефон и кнопку Сохранить

В закладке Text это выглядит вот так:

В закладке Design так:

Далее создадим класс для работы с SQLite, назовем его ControlSQL

Цукерберг рекомендует:  Работа с Google Photo Манипуляции с фотографиями

добавим расширение extends SQLiteOpenHelper

И в этом классе опишем функции работы с базой SQLLite

Получится такой код:

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

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

Давайте при загрузке программы сделаем, чтобы в размещенные на форме поля брались значения из базы SQLLite, а при нажатии кнопки «Сохранить» — чтобы сохранялись измененные значения.

Для записи значений используем .updateTable

Если нужно не сохранять значение, а добавлять в базу, то нужно вызвать функцию .createNewTable

в итоге получился такой код

Когда все скомпилируем (Build-Build APK), получится вот такое приложение, назовем его «Лучший спонсор»:

При первом запуске откроется окно для сохранения настроек, например имени и телефона главного спонсора.

Первоначально поля пустые.

Заносим реквизиты спонсора, нажимаем Сохранить.

Информация сохраняется в базу SQLite.

Когда нужно вспомнить телефон спонсора, запускаем приложение, информация считывается из SQLite, и вуаля — спонсор на связи.

Отображать информацию можно либо в виде набора полей, либо в виде списка.

Для вывода списка используют обычно ListView или RecyclerView.

Save data using SQLite

Saving data to a database is >android.database.sqlite package.

Caution: Although these APIs are powerful, they are fairly low-level and require a great deal of time and effort to use:

  • There is no compile-time verification of raw SQL queries. As your data graph changes, you need to update the affected SQL queries manually. This process can be time consuming and error prone.
  • You need to use lots of boilerplate code to convert between SQL queries and data objects.

For these reasons, we highly recommended using the Room Persistence Library as an abstraction layer for accessing information in your app’s SQLite databases.

Define a schema and contract

One of the main principles of SQL databases is the schema: a formal declaration of how the database is organized. The schema is reflected in the SQL statements that you use to create your database. You may find it helpful to create a companion class, known as a contract class, which explicitly specifies the layout of your schema in a systematic and self-documenting way.

A contract class is a container for constants that define names for URIs, tables, and columns. The contract class allows you to use the same constants across all the other classes in the same package. This lets you change a column name in one place and have it propagate throughout your code.

A good way to organize a contract class is to put definitions that are global to your whole database in the root level of the class. Then create an inner class for each table. Each inner class enumerates the corresponding table’s columns.

Note: By implementing the BaseColumns interface, your inner >_ID that some Andro >CursorAdapter expect it to have. It’s not required, but this can help your database work harmoniously with the Android framework.

For example, the following contract defines the table name and column names for a single table representing an RSS feed:

Kotlin

Create a database using an SQL helper

Once you have defined how your database looks, you should implement methods that create and maintain the database and tables. Here are some typical statements that create and delete a table:

Kotlin

Just like files that you save on the device’s internal storage, Android stores your database in your app’s private folder. Your data is secure, because by default this area is not accessible to other apps or the user.

Note: Because they can be long-running, be sure that you call getWritableDatabase() or getReadableDatabase() in a background thread, such as with AsyncTask or IntentService .

To use SQLiteOpenHelper , create a sub >onCreate() and onUpgrade() callback methods. You may also want to implement the onDowngrade() or onOpen() methods, but they are not required.

For example, here’s an implementation of SQLiteOpenHelper that uses some of the commands shown above:

Kotlin

To access your database, instantiate your sub >SQLiteOpenHelper :

Kotlin

Put information into a database

Insert data into the database by passing a ContentValues object to the insert() method:

Kotlin

The first argument for insert() is simply the table name.

The second argument tells the framework what to do in the event that the ContentValues is empty (i.e., you d >put any values). If you specify the name of a column, the framework inserts a row and sets the value of that column to null. If you specify null , like in this code sample, the framework does not insert a row when there are no values.

The insert() methods returns the ID for the newly created row, or it will return -1 if there was an error inserting the data. This can happen if you have a conflict with pre-existing data in the database.

Read information from a database


To read from a database, use the query() method, passing it your selection criteria and desired columns. The method combines elements of insert() and update() , except the column list defines the data you want to fetch (the «projection»), rather than the data to insert. The results of the query are returned to you in a Cursor object.

Kotlin

The third and fourth arguments ( selection and selectionArgs ) are combined to create a WHERE clause. Because the arguments are prov >query() reference.

To look at a row in the cursor, use one of the Cursor move methods, which you must always call before you begin reading values. Since the cursor starts at position -1, calling moveToNext() places the «read position» on the first entry in the results and returns whether or not the cursor is already past the last entry in the result set. For each row, you can read a column’s value by calling one of the Cursor get methods, such as getString() or getLong() . For each of the get methods, you must pass the index position of the column you desire, which you can get by calling getColumnIndex() or getColumnIndexOrThrow() . When finished iterating through results, call close() on the cursor to release its resources. For example, the following shows how to get all the item IDs stored in a cursor and add them to a list:

Kotlin

Delete information from a database

To delete rows from a table, you need to prov >delete() method. The mechanism works the same as the selection arguments to the query() method. It divides the selection specification into a selection clause and selection arguments. The clause defines the columns to look at, and also allows you to combine column tests. The arguments are values to test against that are bound into the clause. Because the result isn’t handled the same as a regular SQL statement, it is immune to SQL injection.

Kotlin

The return value for the delete() method indicates the number of rows that were deleted from the database.

Update a database

When you need to modify a subset of your database values, use the update() method.

Updating the table combines the ContentValues syntax of insert() with the WHERE syntax of delete() .

Kotlin

The return value of the update() method is the number of rows affected in the database.

Persisting database connection

Since getWritableDatabase() and getReadableDatabase() are expensive to call when the database is closed, you should leave your database connection open for as long as you possibly need to access it. Typically, it is optimal to close the database in the onDestroy() of the calling Activity.

Kotlin

Debug your database

The Andro >sqlite3 shell tool that allows you to browse table contents, run SQL commands, and perform other useful functions on SQLite databases. For more information, see how to how to issue shell commands.

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

Работа с готовой базой данных SQLite под Andro > 01.11.2020 Admin Комментировать

В предыдущей статье посвящённой работе с SQLite в Android приложениях на Java была рассмотрена, если её можно так назвать, «классическая» схема. Когда создаётся пустая база данных, которая впоследствии заполняется в коде программы.

Это вполне оправдано в случае небольших баз данных. Однако работать с крупными объёмами информации или данными сложной структуры таким способом неудобно. В подобных ситуациях имеет смысл создать и заполнить базу данных отдельно от приложения, а затем включить уже готовую базу данных в его состав, несмотря на то, что подобный подход более сложен в отношении реализации.

Способ использования готовой базы данных приведённый в данной статье является универсальным и не требует каких-либо сторонних библиотек и т.д., так как реализован на «чистом» Android SDK.

Важное замечание!

Если вы ранее не работали с SQLite под Android средствами Java, настоятельно рекомендуется вначале ознакомиться со статьёй «Работа с СУБД SQLite под Android на Java», где помимо упомянутой «классической» схемы подробно описаны основы работы с данной СУБД.

Создание базы данных

Создать базу данных можно в любой программе, которая предназначена для администрирования с баз данных СУБД SQLite.

При создании базы данных необходимо учитывать один нюанс.

В Android в базе данных SQLite должна обязательно присутствовать специальная таблица android_metadata. Эта таблица создаётся непосредственно Android и используется в служебных целях.

При работе с базой данных по «классической» схеме, данная таблица создаётся автоматически без участия разработчика. Если же речь идёт об использовании уже готовой базы данных, таблицу android_metadata необходимо создать самостоятельно.

Таблица android_metadata содержит одно единственное поле locale, которое имеет тип данных текст и значение по умолчанию «en_US».

Использование SQLite в Android-разработке. Tips and tricks

Для меня этот проект стал первым, где надо было вплотную использовать SQLite (раньше он был нужен не более, чем для select ).

Задача такова: сканировать штрих-коды товаров, распознавать их, сверять со справочниками и выводить результат пользователю.

В ходе решения сделал несколько интересных для себя выводов.

1) Первичный ключ таблиц не обязательно должен называться «_id».

Это нужно, только если вы хотите отображать таблицу, используя стандартный механизм
ListView — CursorAdapter — LoaderManager — ContentProvider (см. примечание здесь)
В принципе, тривиальное утверждение, описанное в документации, однако как-то (лично у меня, во всяком случае) сложилось представление, что поле первичного ключа в таблицах обязательно должно называться _id. Раньше всегда так делал, не вдаваясь в подробности, во избежание.

Другое название ключа может быть необходимым, если надо импортировать в SQLite уже разработанную ранее структуру таблиц.
В моём случае — у таблиц справочников есть уже свои поля [Something_ID], по которым выполняется присоединение этих таблиц. И логично эти поля сделать первичными ключами, поскольку они будут автоматически проиндексированы.

2) Решение задачи автоматического создания структуры БД и заполнения её начальными данными.

Сначала, при первом запуске приложения думал просто получать данные от удалённого сервера и делать insert таблиц справочников. Это плохой вариант, поскольку данных много (чуть больше 2Mb).

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

Вариант реализации bulkInsert в провайдере:

А хотелось бы, чтобы предзаполненные таблицы с данными уже были готовы к началу работы пользователя с приложением. И нашёлся альтернативный вариант — библиотека android-SQLite-asset-helper

Суть такова: БД создаётся не на устройстве в момент работы, а в процессе разработки приложения, сжимается, зипуется и кладётся в assets. Далее в проекте хелпер работы с БД наследуется не от стандартного SQLiteOpenHelper, а от SQLiteAssetHelper. И всё, при первом обращении пользователя база копируется в приложение, подробности реализации инкапсулированы в хелпере (и мне даже лень было в них вдаваться).

Цукерберг рекомендует:  Метапрограммирование

Подход очень понравился своими преимуществами:

  • Скорость. У меня на копирование 2Мб заполненной базы с десятком таблиц уходит меньше секунды, что происходит ровно 1 раз за всё время жизни приложения.
    Также отсутсуют дополнительные конвертации данных из одного формата в другой (раньше подобную задачу я стал бы решать, положив в assets, скажем, JSON-файл, и начитывая его в базу при первом запуске).
  • Упрощение разработки структуры БД. Отпадает утомительная необходимость писать скрипты создания таблиц в OnCreate хелпера + можно использовать дополнительные приложения для управления SQLite. Для убунту мне понравилась SQLitestudio, простая и понятная. (Хотя и небезглючная, честно сказать — в текущей версии 2.1.4 не может создать триггер для представления, но где не справилась она, доделал через стандартный консольный sqlite3).

3) Особенности взаимодействия представлений (view) SQLite с андроидным LoaderManager.
На вопросах что такое LoaderManager и как им пользоваться, подробно останавливаться не стану, лично мне помог прекрасный цикл статей. Скажу только, что хотел использовать именно LoaderManager, чтобы возложить на него задачу автоматического обновления изменившихся данных в списке.

Однако, вставлять данные надо в таблицу, а отображать — из связанной с ней вьюхи, где вместо id-полей подставлены значения:

В лоб такой вариант, как оказалось, не работает. Для лоадера uri на таблицу и uri на вьюху — два разных uri :)
Т.е. если проинициализировать в нём view_scan, вместо table_scan, то при вставке в таблицу обновления списка не будет.
С таблицей же всё отлично обновляется, но на выходе вместо красивых значений — их ID-ключи, непонятные людям.

Подходящим решением оказался первый же вариант, найденный в документации SQLite. Во вьюху нельзя вставлять данные напрямую (что ожидаемо), но можно создать триггер, который автоматически вставляет их в нужную таблицу.

Ок, дополняю вьюху недостающими id-полями

и пишу триггер вставки:

Теперь всё работает. В LoaderManager при инициализации отдаётся uri вьюхи, запрос на вставку тоже идёт к вьюхе, а всю остальную работу делает SQLite. Лоадер при этом делает то, что должен, т.е. мониторит курсор и автоматически передаёт адаптеру списка изменившиеся данные.

На этом всё. Будет интересно почитать ещё что-нибудь про продвинутые техники работы со SQLite на Android.
Ну и объективная критика тоже интересна :)

Подключение существующей БД SQLite в Andro >Обучающий пример работы с БД SQLite, которая была заранее подготовлена.

10.04.2020 23 комментария 29 015 просмотров

Пример простого Andro >

Содержание

Введение

Есть два подхода к работе с БД в Android приложениях.

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

Но данный способ не очень хорош, если, например, пишите какой-нибудь справочник или другое приложение, когда БД при установке приложения уже должна быть заполнена большим количеством записей. На мой взгляд, в этом случае лучше БД подготовить заранее, а потом уже её подключить как отдельный файл в ресурсах приложения. В данной статье рассмотрен данный случай.

Создание базы данных

Для создания БД SQLite будем использовать, например, DB Browser for SQLite. Скачиваем и устанавливаем.

Буем создавать БД с одной таблицей такого вида.

_id name age
1 Anton 30
2 Alina 24
3 Dima 28
4 Dasha 23

Итак, создаем базу данных.

Где-нибудь сохраняем и называем, например, info.db .

Создаем таблицу, например, clients . И добавляем там поле.

Первым полем у нас будет номер записи _id . Поле будет также первичным ключом.

Аналогичным способом создаем поля age и name . И жмем OK .

В списке таблиц у нас появилась наша таблица clients .

Переходим в режим заполнения таблицы.

Выбираем там нашу таблицу и жмем Добавить запись .

Заполняем наши данные и сохраняем изменения в БД.

Создание Android проекта

Открываем Android Studio и создаем там новый проект с пустой активностью. Всё как обычно.

Разметка активности


Так как мы создаем простейшее приложение, но в xml файле активности разместим только кнопку и поле для вывода текста.

Подготовка Java кода

Нам потребуется обработать клик на кнопку button и что-то записать в textView .

Поэтому найдем данные компоненты и свяжем их в java коде с xml.

Объявим переменные компонентов.

Найдем компоненты в XML разметке.

Пропишем обработчик клика кнопки.

Полный код java файла.

Добавление БД в проект

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

Создадим папку assets в нашем проекте.

Скопируем файл нашей базы данных.

Добавление класса для работы с БД

Для открытия и подготовки БД в Andro >SQLiteOpenHelper . Мы тоже создадим наследник этого класса DatabaseHelper , но он будет сильно модифицированный, так как мы будем работать с готовой базой данных, а не создавать ей с помощью SQL запросов.

Ниже приведен текст всего класса, который нужно просто скопировать.

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

Разберем что означают эти строчки.

DB_NAME — имя файла БД. Какой файл БД вы создали, такое название сюда и копируем.

DB_PATH — путь к БД. Каждое приложение в Android имеет свою область памяти, куда складываются файлы программы. Вдруг вы захотите вывернуть путь к файлу БД. Я бы ничего не трогал.

DB_VERSION — самая интересная переменная (причем в примерах в сети по работе с готовой БД её обходят стороной). Это номер версии БД. Ниже описан принцип работы данного класса. Например, вы пишите справочник рецептов под Android и рецепты храните в БД. В момент создания установки приложения программа должна скопировать БД на устройство. Потом через какое-то время вы решили обновить приложение, и БД у вас обновилась: структура БД поменялась, добавились новые рецепты. И вам нужно заменить старую БД на новую. Вот тут вы и пропишите в данной переменной новую версию БД. И при открытии приложения будет произведена проверки версии БД и файл БД обновится. Вначале версия БД равна 1.

Итак, логика работы класса DatabaseHelper в подготовке базы данных.

Копируем файл БД, если этого файла нет (при установке приложения).

Если номер БД обновлен, то заменяем один файл базы данных на другой.

После работы с базой данных из данного класса вытаскиваем экземпляр SQLiteDatabase , с которым будем работать в дальнейшем: осуществлять запросы и так далее.

Подключаемся к БД

Перейдем в класс нашей активности. В нем создадим экземпляр класса DatabaseHelper , попытаемся обновить БД, если это требуется, а потом вытащим экземпляр SQLiteDatabase .

Создаём приложение заметок. Основы работы с SQLite в Andro >

В прошлых уроках мы создали своё первое серьёзное приложение, позволяющее устанавливать и удалять приложения.

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

Давайте же сформулируем задачу, которую мы решим за ближайшие несколько уроков: создать приложение, которое позволит создавать, хранить, удалять и редактировать заметки. Приложение должно уметь не только сохранять текст (это слишком уж банально), но и прикреплять фотографии.

Ну и, конечно же, всё это будет реализовано с использованием Material Design.

Работа с SQLite

В Android, как и в iOS, есть встроенная в систему компактная база данных — SQLite.

SQLite обладает рядом недостатков — например, в него нельзя писать данные одновременно из нескольких потоков. Однако, все эти недостатки перекрываются огромным (для мобильных устройств) преимуществом: она чрезвычайно компактна.

Вся база данных хранится в одном-единственном файле, и, хоть и работает она относительно медленно (по сравнению со «старшими братьями»; для своих целей она является очень даже шустрой), но при этом занимает очень мало места и способна работать даже на самых слабых устройствах.

Чтобы понять, как оно работает, давайте попробуем поработать с SQLite на компьютере. Если вы не знакомы с SQL, рекомендую ознакомиться с этой статьёй и ссылками в ней.

В практике работы с SQLite нам поможет приложение SQLite Database Browser. Оно полностью бесплатно, работает на macOS, Windows и Linux, и исходный код доступен на GitHub. Скачайте и установите его.

После установки запустите приложение и нажмите на кнопку New Database:

Кнопка «New Database»

Введите имя и расположения файла, в котором будет создана БД и нажмите на кнопку Save:

Выбор файла для сохранения БД

После этого появится диалог, предлагающий создать таблицу. Закройте его — мы будем создавать её вручную.

Выберите вкладку Execute SQL:

Вкладка «Execute SQL»

Для начала нам нужна одна таблица, в которой мы будем хранить заметки. В таблице будут такие столбцы:

  • id — integer , primary key . Идентификатор заметки.
  • title — text , заголовок заметки.
  • note — text , текст заметки.
  • created_ts — integer , дата создания заметки в формате unix time.
  • updated_ts — integer , дата последнего изменения заметки в формате unix time.

SQL-запрос для создания таблицы будет таким:

Введите его в поле для запроса и нажмите на кнопку Execute SQL. Результат выполнения появится в окне ниже:

Результат выполнения SQL

Теперь вернемся на вкладку Database Structure и посмотрим, что получилось:

Структура БД SQLite

Отлично. Теперь вставим первую заметку в нашу таблицу:

В качестве времени создания и обновления для простоты передадим 0 , то есть начало эпохи UNIX. Выполните этот запрос и перейдите на вкладку Browse Data:

Данные в БД SQLite

Как видите, данные вставились успешно. Добавьте ещё одну заметку:

У неё мы изменили время создания и редактирования.

Зачем? Чтобы показать работу сортировки в SQLite. Мы будем показывать первыми те заметки, которые были изменены последними.

Если вы выполните следующий запрос:

То получите вот такой результат:

Результат выполнения SELECT

То есть первой показывается первая заметка. А теперь выполните вот такой запрос:

В нём мы говорим базе данных, что нужно отсортировать данные по полю updated_ts , при этом сортировку нужно выполнить по убыванию. Результатом будет следующий набор данных:

Данные в БД SQLite с сортировкой

Теперь давайте попробуем обновить заметку:

Главное — не забыть WHERE , иначе обновятся все строки в таблице.

Ну и удалим заметку:

Последняя вещь, о которой нужно узнать — это индексы. Если у пользователя будет много заметок, то сортировка может занимать достаточно продолжительное время, в результате, список заметок будет отображаться с лагами. Поэтому нам нужно создать индекс по столбцу updated_ts :

Вот и всё! Примерно то же самое мы будем делать в нашем приложении.

SQLite в Android

Работа с SQLite в Android отличается от того, что мы делали ранее всего парой аспектов:

  • Вам почти никогда не придётся работать с «сырыми» SQL-запросами — для вставки/получения/удаления записей есть удобные методы.
  • Стандартное для большинства движков БД имя столбца id в Android по какой-то неведомой причине принято заменять на _id . Лучше следовать этому стандарту, иначе некоторые вещи могут сломаться.

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

Создайте новый проект, как мы делали это ранее. В прошлом проекте мы хранили все файлы в одном пакете. В этом мы более аккуратно подойдём к организации. Начнём, собственно, с БД.

Внутри основного пакета создайте пакет db :

Создание нового пакета

Контракт БД

В пакете db , который мы создали ранее, создайте класс NotesContract :

Этот класс облегчит работу с БД, а так же будет выступать в качестве «документации» структуры нашей БД для тех, кто возможно будет смотреть наши исходники. В нём мы будем описывать таблицы, которые будут присутствовать в БД.

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих