В Android имеется встроенная поддержка одной из распространенных систем управления базами данных - SQLite. Для этого в пакете android.database.sqlite определен набор классов, которые позволяют работать с базами данных SQLite. И каждое приложение может создать свою базу данных.
Чтобы использовать SQLite в Android, надо создать базу данных с помощью выражение на языке SQL. После этого база данных будет храниться в каталоге приложения по пути:
DATA/data/[Название_приложения]/databases/[Название_файла_базы_данных]
ОС 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 в Android мы можем вызвать метод openOrCreateDatabase(). Этот метод может принимать три параметра:
название для базы данных
числовое значение, которое определяет режим работы (как правило, в виде константы MODE_PRIVATE)
необязательный параметр в виде объекта SQLiteDatabase.CursorFactory, который представляет фабрику создания курсора для работы с бд
Например, создание базы данных app.db:
SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null);
Для выполнения запроса к базе данных можно использовать метод execSQL класса SQLiteDatabase. В этот метод передается SQL-выражение. Например, создание в базе данных таблицы users:
SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)");
Если нам надо не просто выполнить выражение, но и получить из бд какие-либо данные, то используется метод rawQuery(). Этот метод в качестве параметра принимает SQL-выражение, а также набор значений для выражения sql. Например, получение всех объектов из базы данных:
SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)");
Cursor query = db.rawQuery("SELECT * FROM users;", null);
if(query.moveToFirst()){
String name = query.getString(0);
int age = query.getInt(1);
}
Метод db.rawQuery() возвращает объект Cursor, с помощью которого мы можем извлечь полученные данные.
Возможна ситуация, когда в базе данных не будет объектов, и для этого методом query.moveToFirst() пытаемся переместиться к первому
объекту, полученному из бд. Если этот метод возвратит значение false, значит запрос не получил никаких данных из бд.
Теперь для работы с базой данных сделаем простейшее приложение. Для этого создадим новый проект.
В файле activity_main.xml определим простейший графический интерфейс:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click"
android:onClick="onClick"
app:layout_constraintBottom_toTopOf="@id/textView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
app:layout_constraintTop_toBottomOf="@id/button"
app:layout_constraintLeft_toLeftOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
А в классе MainActivity определим взаимодействие с базой данных:
package com.example.sqliteapp;
import androidx.appcompat.app.AppCompatActivity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view){
SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER, UNIQUE(name))");
db.execSQL("INSERT OR IGNORE INTO users VALUES ('Tom Smith', 23), ('John Dow', 31);");
Cursor query = db.rawQuery("SELECT * FROM users;", null);
TextView textView = findViewById(R.id.textView);
textView.setText("");
while(query.moveToNext()){
String name = query.getString(0);
int age = query.getInt(1);
textView.append("Name: " + name + " Age: " + age + "\n");
}
query.close();
db.close();
}
}
По нажатию на кнопку здесь вначале создается в базе данных app.db новая таблица users, а затем в нее добавляются два объекта в базу данных с помощью SQL-выражения INSERT.
Далее с помощью выражения SELECT получаем всех добавленных пользователей из базы данных в виде курсора Cursor.
Вызовом query.moveToNext() перемещаемся в цикле while последовательно по всем объектам.
Для получения данных из курсора применяются методы query.getString(0) и query.getInt(1). В скобках в методы передается
номер столбца, из которого мы получаем данные. Например, выше мы добавили вначале имя пользователя в виде строки, а затем возраст в виде числа. Значит, нулевым столбцом
будет идти строкое значение, которое получаем с помощью метода getString(), а следующим - первым столбцом идет числовое значение, для
которого применяется метод getInt().
После завершения работы с курсором и базой данных мы закрываем все связанные объекты:
query.close(); db.close();
Если мы не закроем курсор, то можем столкнуться с проблемой утечки памяти.
И если мы обратимся к приложению, то после нажатия на кнопку в текстовое поле будут выведены добавленные данные: