Поиск по сайту:

Учебное пособие по примерам базы данных 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 предназначен для избавления от двух очень распространенных проблем.

  1. Когда приложение запускается в первый раз. На данный момент у нас еще нет базы данных. Поэтому нам нужно будет создать таблицы, индексы, начальные данные и т. д.
  2. При обновлении приложения до более новой схемы наша база данных по-прежнему будет использовать старую схему из старой версии приложения. У нас будет возможность изменить схему базы данных, чтобы она соответствовала потребностям остальной части приложения.

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

  1. 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);
        }
    
  2. 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.

  3. 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