Добро пожаловать в руководство по примеру использования Android SQLite. Android SQLite – это предпочтительный способ хранения данных для приложений Android. Для многих приложений SQLite является основой, будь то использование его напрямую или через оболочку от стороннего разработчика. Ниже приведено окончательное приложение, которое мы создадим сегодня, используя базу данных Android SQLite.
Android SQLite
Android SQLite – это очень легкая база данных, поставляемая с операционной системой Android. Android SQLite объединяет чистый SQL-интерфейс с небольшим объемом памяти и приличной скоростью. Для Android SQLite является частью Android Runtime, поэтому каждое приложение Android может создавать свои собственные базы данных SQLite. Нативный API Android SQLite – это не JDBC, так как JDBC может быть излишним для смартфона с ограниченным объемом памяти. После успешного создания базы данных она находится по пути data/data//databases/ и доступна из Android Device Monitor. SQLite – типичная реляционная база данных, содержащая таблицы (которые состоят из строк и столбцов), индексы и так далее. Мы можем создавать свои собственные таблицы для хранения данных в соответствии с их структурой. Эта структура называется схемой.
Android SQLite SQLiteOpenHelper
Android имеет функции для работы с изменением схемы базы данных, которые в основном зависят от использования класса SQLiteOpenHelper
. Класс SQLiteOpenHelper предназначен для решения двух очень распространенных проблем.
- Когда приложение запускается впервые – на этом этапе у нас еще нет базы данных. Поэтому нам придется создать таблицы, индексы, стартовые данные и так далее.
- Когда приложение обновляется до новой схемы – наша база данных все еще остается на старой схеме от предыдущей версии приложения. У нас будет возможность изменить схему базы данных, чтобы соответствовать потребностям остальной части приложения.
SQLiteOpenHelper
инкапсулирует эту логику создания и обновления базы данных в соответствии с нашими требованиями. Для этого нам нужно создать пользовательский подкласс SQLiteOpenHelper
, реализуя как минимум следующие три метода.
-
Конструктор: Принимает контекст (например, Activity), имя базы данных, необязательный курсорный фабрикат (о котором мы поговорим позже) и целочисленное значение, представляющее версию схемы базы данных, которую вы используете (обычно начиная с 1 и увеличивая позже).
public DatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); }
-
onCreate(SQLiteDatabase db): Вызывается, когда базы данных нет, и приложению нужна одна. Он передает нам объект
SQLiteDatabase
, указывающий на только что созданную базу данных, которую мы можем заполнить таблицами и начальными данными. -
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion): Вызывается, когда версия схемы, которую нам нужно использовать, не соответствует версии схемы базы данных. Он передает нам объект SQLiteDatabase и старую и новую версии. Таким образом, мы можем выяснить лучший способ преобразовать базу данных из старой схемы в новую.
Мы определяем класс DBManager
, чтобы выполнять все операции CRUD (Create, Read, Update и Delete) с базой данных.
Открытие и закрытие подключения к базе данных Android SQLite
Перед выполнением любых операций с базой данных, таких как вставка, обновление, удаление записей в таблице, сначала откройте подключение к базе данных, вызвав метод getWritableDatabase(), как показано ниже:
public DBManager open() throws SQLException {
dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
return this;
}
dbHelper – это экземпляр подкласса SQLiteOpenHelper
. Чтобы закрыть подключение к базе данных, вызывается следующий метод.
public void close() {
dbHelper.close();
}
Вставка новой записи в таблицу базы данных Android SQLite
Ниже приведен фрагмент кода, показывающий, как вставить новую запись в базу данных Android SQLite.
public void insert(String name, String desc) {
ContentValues contentValue = new ContentValues();
contentValue.put(DatabaseHelper.SUBJECT, name);
contentValue.put(DatabaseHelper.DESC, desc);
database.insert(DatabaseHelper.TABLE_NAME, null, contentValue);
}
Content Values создает пустой набор значений с заданным начальным размером. Другие значения экземпляра будут рассмотрены, когда мы перейдем к части кодирования.
Обновление записи в таблице базы данных Android SQLite
В следующем фрагменте показано, как обновить одну запись.
public int update(long _id, String name, String desc) {
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.SUBJECT, name);
contentValues.put(DatabaseHelper.DESC, desc);
int i = database.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper._ID + " = " + _id, null);
return i;
}
Android SQLite – Удаление записи
Нам просто нужно передать идентификатор записи, которую нужно удалить, как показано ниже.
public void delete(long _id) {
database.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper._ID + "=" + _id, null);
}
Android SQLite Cursor
A Cursor represents the entire result set of the query. Once the query is fetched a call to cursor.moveToFirst() is made. Calling moveToFirst() does two things:
- Это позволяет нам проверить, вернулся ли пустой набор записей (путем проверки возвращаемого значения)
- Он перемещает курсор к первому результату (когда набор не пуст)
Следующий код используется для извлечения всех записей:
public Cursor fetch() {
String[] columns = new String[] { DatabaseHelper._ID, DatabaseHelper.SUBJECT, DatabaseHelper.DESC };
Cursor cursor = database.query(DatabaseHelper.TABLE_NAME, columns, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
Еще один способ использования Cursor – обернуть его в CursorAdapter
. Точно так же, как ArrayAdapter
адаптирует массивы, CursorAdapter
адаптирует объекты Cursor, предоставляя их данные AdapterView
, такому как ListView
. Перейдем к нашему проекту, который использует SQLite для хранения каких-то значимых данных.
Пример структуры проекта Android SQLite
В этом приложении мы хотим создать записи, которые хранят названия стран и их соответствующие валюты в виде ListView. Мы охватываем все функции, обсуждаемые выше.
Код проекта Android SQLite
Приложение состоит из 5 классов. Мы начинаем с определения с DatabaseHelper, который является подклассом SQLiteOpenHelper следующим образом: DatabaseHelper.java
package com.journaldev.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
// Имя таблицы
public static final String TABLE_NAME = "COUNTRIES";
// Столбцы таблицы
public static final String _ID = "_id";
public static final String SUBJECT = "subject";
public static final String DESC = "description";
// Информация о базе данных
static final String DB_NAME = "JOURNALDEV_COUNTRIES.DB";
// Версия базы данных
static final int DB_VERSION = 1;
// Запрос на создание таблицы
private static final String CREATE_TABLE = "create table " + TABLE_NAME + "(" + _ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + SUBJECT + " TEXT NOT NULL, " + DESC + " TEXT);";
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
Как обсуждалось выше, мы переопределили методы onCreate()
и onUpgrade()
, помимо конструктора. Мы присвоили имена базе данных и таблице как JOURNALDEV_COUNTRIES.DB и COUNTRIES соответственно. Индексный столбец автоматически увеличивается при вставке новой строки. Имена столбцов для страны и валюты – “subject” и “description”. Класс DBManager – это место, где инициализируется DatabaseHelper и определяются операции CRUD. Ниже приведен код для этого класса: DBManager.java
package com.journaldev.sqlite;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
public class DBManager {
private DatabaseHelper dbHelper;
private Context context;
private SQLiteDatabase database;
public DBManager(Context c) {
context = c;
}
public DBManager open() throws SQLException {
dbHelper = new DatabaseHelper(context);
database = dbHelper.getWritableDatabase();
return this;
}
public void close() {
dbHelper.close();
}
public void insert(String name, String desc) {
ContentValues contentValue = new ContentValues();
contentValue.put(DatabaseHelper.SUBJECT, name);
contentValue.put(DatabaseHelper.DESC, desc);
database.insert(DatabaseHelper.TABLE_NAME, null, contentValue);
}
public Cursor fetch() {
String[] columns = new String[] { DatabaseHelper._ID, DatabaseHelper.SUBJECT, DatabaseHelper.DESC };
Cursor cursor = database.query(DatabaseHelper.TABLE_NAME, columns, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public int update(long _id, String name, String desc) {
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.SUBJECT, name);
contentValues.put(DatabaseHelper.DESC, desc);
int i = database.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper._ID + " = " + _id, null);
return i;
}
public void delete(long _id) {
database.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper._ID + "=" + _id, null);
}
}
Класс CountryListActivity.java
– это активность, которая запускается при запуске приложения. Ниже приведен макет, определенный для нее: fragment_emp_list.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="1dp"
android:padding="10dp" >
</ListView>
<TextView
android:id="@+id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/empty_list_text" />
</RelativeLayout>
Здесь определен компонент ListView для включения записей, хранящихся в базе данных. Изначально ListView будет пустым, поэтому используется TextView для отображения этого же. CountryListActivity.java
package com.journaldev.sqlite;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
public class CountryListActivity extends ActionBarActivity {
private DBManager dbManager;
private ListView listView;
private SimpleCursorAdapter adapter;
final String[] from = new String[] { DatabaseHelper._ID,
DatabaseHelper.SUBJECT, DatabaseHelper.DESC };
final int[] to = new int[] { R.id.id, R.id.title, R.id.desc };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_emp_list);
dbManager = new DBManager(this);
dbManager.open();
Cursor cursor = dbManager.fetch();
listView = (ListView) findViewById(R.id.list_view);
listView.setEmptyView(findViewById(R.id.empty));
adapter = new SimpleCursorAdapter(this, R.layout.activity_view_record, cursor, from, to, 0);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
// OnCLickListiner для элементов списка
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView > parent, View view, int position, long viewId) {
TextView idTextView = (TextView) view.findViewById(R.id.id);
TextView titleTextView = (TextView) view.findViewById(R.id.title);
TextView descTextView = (TextView) view.findViewById(R.id.desc);
String id = idTextView.getText().toString();
String title = titleTextView.getText().toString();
String desc = descTextView.getText().toString();
Intent modify_intent = new Intent(getApplicationContext(), ModifyCountryActivity.class);
modify_intent.putExtra("title", title);
modify_intent.putExtra("desc", desc);
modify_intent.putExtra("id", id);
startActivity(modify_intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.add_record) {
Intent add_mem = new Intent(this, AddCountryActivity.class);
startActivity(add_mem);
}
return super.onOptionsItemSelected(item);
}
}
В этой активности объект DBManager вызывается для выполнения операций CRUD. Определен SimpleCursorAdapter для добавления элементов в список из результатов запроса, возвращенных в объекте Cursor. При нажатии на элемент списка выполняется намерение открыть класс ModifyCountryActivity. В меню содержится элемент для добавления новой записи из панели действий. Здесь снова выполняется намерение открыть класс AddCountryActivity. Ниже приведен код menu.xml
. menu.xml
<menu xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
tools:context="com.example.sqlitesample.MainActivity" >
<item
android:id="@+id/add_record"
android:icon="@android:drawable/ic_menu_add"
android:orderInCategory="100"
android:title="@string/add_record"
app:showAsAction="always"/>
</menu>
Макет и код xml файла AddCountryActivity.java
определены ниже: activity_add_record.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp" >
<EditText
android:id="@+id/subject_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/enter_title" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/description_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/enter_desc"
android:inputType="textMultiLine"
android:minLines="5" >
</EditText>
<Button
android:id="@+id/add_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/add_record" />
</LinearLayout>
Определены два компонента EditText, которые принимают ввод для страны и валюты, а также кнопка для добавления значений в базу данных и их отображения в ListView. AddCountryActivity.java
package com.journaldev.sqlite;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class AddCountryActivity extends Activity implements OnClickListener {
private Button addTodoBtn;
private EditText subjectEditText;
private EditText descEditText;
private DBManager dbManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Add Record");
setContentView(R.layout.activity_add_record);
subjectEditText = (EditText) findViewById(R.id.subject_edittext);
descEditText = (EditText) findViewById(R.id.description_edittext);
addTodoBtn = (Button) findViewById(R.id.add_record);
dbManager = new DBManager(this);
dbManager.open();
addTodoBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.add_record:
final String name = subjectEditText.getText().toString();
final String desc = descEditText.getText().toString();
dbManager.insert(name, desc);
Intent main = new Intent(AddCountryActivity.this, CountryListActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(main);
break;
}
}
}
Здесь выполняется операция CRUD – добавление новой записи в базу данных. Макет и код файла ModifyCountryActivity.java определены ниже: activity_modify_record.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp" >
<EditText
android:id="@+id/subject_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:ems="10"
android:hint="@string/enter_title" />
<EditText
android:id="@+id/description_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/enter_desc"
android:inputType="textMultiLine"
android:minLines="5" >
</EditText>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="2"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/btn_update" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/btn_delete" />
</LinearLayout>
</LinearLayout>
Он похож на предыдущий макет, за исключением того, что добавлены кнопки для изменения и удаления. ModifyCountryActivity.java
package com.journaldev.sqlite;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class ModifyCountryActivity extends Activity implements OnClickListener {
private EditText titleText;
private Button updateBtn, deleteBtn;
private EditText descText;
private long _id;
private DBManager dbManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Modify Record");
setContentView(R.layout.activity_modify_record);
dbManager = new DBManager(this);
dbManager.open();
titleText = (EditText) findViewById(R.id.subject_edittext);
descText = (EditText) findViewById(R.id.description_edittext);
updateBtn = (Button) findViewById(R.id.btn_update);
deleteBtn = (Button) findViewById(R.id.btn_delete);
Intent intent = getIntent();
String id = intent.getStringExtra("id");
String name = intent.getStringExtra("title");
String desc = intent.getStringExtra("desc");
_id = Long.parseLong(id);
titleText.setText(name);
descText.setText(desc);
updateBtn.setOnClickListener(this);
deleteBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_update:
String title = titleText.getText().toString();
String desc = descText.getText().toString();
dbManager.update(_id, title, desc);
this.returnHome();
break;
case R.id.btn_delete:
dbManager.delete(_id);
this.returnHome();
break;
}
}
public void returnHome() {
Intent home_intent = new Intent(getApplicationContext(), CountryListActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(home_intent);
}
}
Операции CRUD, выполняемые здесь, включают обновление и удаление записи. Ниже представлены снимки экрана финального результата нашего проекта. Первое изображение – это результат запуска приложения в первый раз. Второе изображение – результат выбора опции меню из ActionBar для добавления новой записи, как показано ниже.
Третье изображение показывает результат, когда добавлено 3 записи:
Четвертое изображение отображает результат, когда производится щелчок по элементу списка для изменения или удаления записи:
Последнее изображение – результат удаления записи. В этом примере мы удаляем первую запись:
Открытие файла базы данных Android SQLite
Как мы обсуждали ранее в этом руководстве, файл базы данных хранится во внутреннем хранилище, к которому можно получить доступ из монитора устройства Android, как показано на рисунке ниже. Для просмотра этой базы данных нам нужно извлечь этот файл с устройства на наш рабочий стол. Это делается, нажав в верхнем правом углу на пункт меню, как показано на изображении ниже:
Для открытия этого файла загрузите SQLiteBrowser по ссылке this. Ниже приведены отрывки, показывающие схему и таблицы в браузере.
Чтобы просмотреть таблицу, перейдите на вкладку Browse Data сверху. Видно следующее изображение:
Это завершает руководство по Android SQLite. Итоговый проект Android SQLite можно загрузить по ссылке ниже.
Source:
https://www.digitalocean.com/community/tutorials/android-sqlite-database-example-tutorial