Учебное пособие по примерам базы данных Android SQLite
SQLite для Android
Android SQLite — очень легкая база данных, которая поставляется с ОС Android. Android SQLite сочетает в себе чистый интерфейс SQL с очень небольшим объемом памяти и приличной скоростью. Для Android SQLite «встроен» в среду выполнения Android, поэтому каждое приложение Android может создавать свои собственные базы данных SQLite. Собственный API Android SQLite не является JDBC, поскольку JDBC может быть слишком накладным для смартфона с ограниченным объемом памяти. успешно создан, он находится в data/data//databases/, доступном из Android Device Monitor.SQLite — типичная реляционная база данных, содержащая таблицы (состоящие из строк и столбцов), индексы и т. д. Мы можем создавать собственные таблицы для хранения данных соответственно Эта структура называется схемой.
Android SQLite SQLiteOpenHelper
В Android есть функции для обработки изменяющихся схем базы данных, которые в основном зависят от использования класса SQLiteOpenHelper
. SQLiteOpenHelper предназначен для избавления от двух очень распространенных проблем.
- Когда приложение запускается в первый раз. На данный момент у нас еще нет базы данных. Поэтому нам нужно будет создать таблицы, индексы, начальные данные и т. д.
- При обновлении приложения до более новой схемы наша база данных по-прежнему будет использовать старую схему из старой версии приложения. У нас будет возможность изменить схему базы данных, чтобы она соответствовала потребностям остальной части приложения.
SQLiteOpenHelper
завершает эту логику для создания и обновления базы данных в соответствии с нашими спецификациями. Для этого нам нужно создать собственный подкласс SQLiteOpenHelper
, реализующий как минимум следующие три метода.
-
Constructor : This takes the Context (e.g., an Activity), the name of the database, an optional cursor factory (we’ll discuss this later), and an integer representing the version of the database schema you are using (typically starting from 1 and increment later).
public DatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); }
-
onCreate(SQLiteDatabase db) : It’s called when there is no database and the app needs one. It passes us a
SQLiteDatabase
object, pointing to a newly-created database, that we can populate with tables and initial data. -
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) : It’s called when the schema version we need does not match the schema version of the database, It passes us a SQLiteDatabase object and the old and new version numbers. Hence we can figure out the best way to convert the database from the old schema to the new one.
Мы определяем класс DBManager
для выполнения всех операций базы данных CRUD (создание, чтение, обновление и удаление).
Открытие и закрытие подключения к базе данных 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.moveToFirst(). Вызов moveToFirst() делает две вещи:
- Это позволяет нам проверить, вернул ли запрос пустой набор (проверив возвращаемое значение)
- Перемещает курсор к первому результату (если набор не пуст)
Следующий код используется для получения всех записей:
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;
}
Другой способ использования курсора — поместить его в CursorAdapter
. Точно так же, как ArrayAdapter
адаптирует массивы, CursorAdapter
адаптирует объекты Cursor, делая их данные доступными для AdapterView
, такого как ListView
. Давайте перейдем к нашему проекту, который использует SQLite для хранения некоторых значимых данных.
Пример структуры проекта Android SQLite
Код проекта 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 {
// Table Name
public static final String TABLE_NAME = "COUNTRIES";
// Table columns
public static final String _ID = "_id";
public static final String SUBJECT = "subject";
public static final String DESC = "description";
// Database Information
static final String DB_NAME = "JOURNALDEV_COUNTRIES.DB";
// database version
static final int DB_VERSION = 1;
// Creating table query
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 соответственно. Столбец индекса автоматически увеличивается всякий раз, когда вставляется новая строка. Имена столбцов для страны и валюты — «тема» и «описание». В классах 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 For List Items
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 добавляет новую запись в базу данных. Макет xml и код файла 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);
}
}
Открытие файла базы данных Android SQLite
Скачать пример проекта Android SQLite