Работа с БД в Android-приложении с использованием SQLightOpenHelper, Cheat Sheet of Mathematics

Данный документ посвящен созданию класса-потомка SQLightOpenHelper для работы с БД в Android-приложении. А именно переопределению методов onCreate() для создания БД и onUpgrade() для обновления БД в случае изменений в схеме базы данных. Кроме того, рассматриваются методы getReadableDatabase() и getWriteableDatabase() для доступа к объекту SQLiteDatabase, а также создание, чтение, обновление и удаление данных в БД.

Typology: Cheat Sheet

2020/2021

Uploaded on 05/04/2021

hamidulla-abdulhakimov
hamidulla-abdulhakimov 🇺🇿

3 documents

1 / 18

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Работа с базами данных. Использование SQLite. Создание запросов.
Цель лабораторной работы:
Приобретение навыков работы с базами данных в приложениях Android и
использование SQLite. Создание запросов. Приобретение навыков создания
контент-провайдеров.
Задачи лабораторной работы:
Создание приложения в Androidе с использованием базы данных
Создание запросов
Использование контент провайдеров
Методические указания для выполнения работы
SQLite — это база данных с открытыми исходными кодами, включаемая
по умолчанию в состав Android. SQLite поддерживает стандартные
возможности реляционных баз данных синтаксис, транзакции и prepared
statements. Кроме SQLite требует очень небольшого количества памяти для
работы (примерно 250 кб).
Для работы с БД в Android-приложении обычно создается класс-потомок
SQLightOpenHelper. В этом классе следует переопределить методы onCreate()
для создания БД и onUpgrade() для обновления БД в случае изменений в схеме
базы данных. Оба метода работают с объектом SQLiteDatabase.
SQLiteOpenHelper предоставляет методы getReadableDatabase() и
getWriteableDatabase() для доступа к объекту SQLiteDatabase, который
позволяет читать и писать в БД.
Для первичного ключа БД всегда необходимо использовать
идентификатор «_id», т.к. некоторые функции Android следуют этомуid», т.к. некоторые функции Android следуют этому
стандарту.
Класс SQLiteDatabase предоставляет методы insert(), update(), delete() и
execSQL() (который дает возможность напрямую выполнять SQL-запросы).
Объект ContentValues позволяет определить ключи/значения для вставки и
обновления данных.
Запросы могут быть созданы либо через метод rawQuery(), принимающий
SQL, либо метод query(), предоставляющий интерфейс для указания
динамических данных SQLiteQueryBuilder. SQLiteQueryBuilder схож с
интерфейсом провайдера данных (сontent provider), поэтому обычно он
используется для работы с провайдерами данных.
Запрос к БД всегда возвращает «курсор», представляющий собой
результат запроса. Чтобы получить число элементов в запросе, мы можем
воспользоваться методом getCount(). Для перемещения между записями в
результате используются методы moveToFirst() и moveToNext(). Метод
isAfterLast() позволяет проверить, есть ли еще данные в результате.
Метод выполнения запроса query() имеет параметры: String dbName, int[]
columnNames, String whereClause, String[] valuesForWhereClause, String[]
groupBy, String[] having, String[] orderBy.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12

Partial preview of the text

Download Работа с БД в Android-приложении с использованием SQLightOpenHelper and more Cheat Sheet Mathematics in PDF only on Docsity!

Работа с базами данных. Использование SQLite. Создание запросов. Цель лабораторной работы: Приобретение навыков работы с базами данных в приложениях Android и использование SQLite. Создание запросов. Приобретение навыков создания контент-провайдеров. Задачи лабораторной работы:  Создание приложения в Androidе с использованием базы данных  Создание запросов  Использование контент провайдеров Методические указания для выполнения работы SQLite — это база данных с открытыми исходными кодами, включаемая по умолчанию в состав Android. SQLite поддерживает стандартные возможности реляционных баз данных – синтаксис, транзакции и prepared statements. Кроме SQLite требует очень небольшого количества памяти для работы (примерно 250 кб). Для работы с БД в Android-приложении обычно создается класс-потомок SQLightOpenHelper. В этом классе следует переопределить методы onCreate() для создания БД и onUpgrade() для обновления БД в случае изменений в схеме базы данных. Оба метода работают с объектом SQLiteDatabase. SQLiteOpenHelper предоставляет методы getReadableDatabase () и getWriteableDatabase () для доступа к объекту SQLiteDatabase, который позволяет читать и писать в БД. Для первичного ключа БД всегда необходимо использовать идентификатор «_id», т.к. некоторые функции Android следуют этомуid», т.к. некоторые функции Android следуют этому стандарту. Класс SQLiteDatabase предоставляет методы insert (), update (), delete () и execSQL () (который дает возможность напрямую выполнять SQL-запросы). Объект ContentValues позволяет определить ключи/значения для вставки и обновления данных. Запросы могут быть созданы либо через метод rawQuery (), принимающий SQL, либо метод query (), предоставляющий интерфейс для указания динамических данных SQLiteQueryBuilder. SQLiteQueryBuilder схож с интерфейсом провайдера данных (сontent provider), поэтому обычно он используется для работы с провайдерами данных. Запрос к БД всегда возвращает «курсор», представляющий собой результат запроса. Чтобы получить число элементов в запросе, мы можем воспользоваться методом getCount(). Для перемещения между записями в результате используются методы moveToFirst() и moveToNext(). Метод isAfterLast() позволяет проверить, есть ли еще данные в результате. Метод выполнения запроса query() имеет параметры: String dbName, int[] columnNames, String whereClause, String[] valuesForWhereClause, String[] groupBy, String[] having, String[] orderBy.

Как видите, они соответствуют синтаксису SQL-запросов. Если вам нужно выбрать все данные, используйте null в условии where (null можно указать вместо любого из параметров запроса, например groupBy, orderBy и т.п.). Вообще условие where указывается без самого слова where, например: «_id», т.к. некоторые функции Android следуют этомуid = 19 and summary = ?». ». Возвращаемый курсор может быть использован напрямую с помощью SimpleCursorAdapter в ListViews. Мы создадим приложение «Список дел», которое позволяет пользователю вести список дел, которые нужно выполнить. Эти дела будут сохраняться в БД SQLite. Приложение будет состоять из двух активити, одно для просмотра всего списка дел и второе для создания конкретного дела. Связь между активити будет поддерживаться с помощью интентов. Результат будет выглядеть вот так: Рис. 7.1. Приложение «Список дел» Создайте проект «de.vogella.android.todos» с активити «TodosOverview» и добавьте еще одно активити«TodoDetails». Затем создайте пакет «de.vogella.android.todos.database», в котором будут содержаться классы для работы с базой данных. Начнем с создания следующего класса «TodoDatabaseHelper»: package de.vogella.android.todos.database; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; public class TodoDatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_id», т.к. некоторые функции Android следуют этомуNAME = "applicationdata"; private static final int DATABASE_id», т.к. некоторые функции Android следуют этомуVERSION = 1; // запрос на создание базы данных

private SQLiteDatabase database; private TodoDatabaseHelper dbHelper; public TodoDbAdapter(Context context) { this.context = context; } public TodoDbAdapter open() throws SQLException { dbHelper = new TodoDatabaseHelper(context); database = dbHelper.getWritableDatabase(); return this; } public void close() { dbHelper.close(); } /** создать новый элемент списка дел. если создан успешно - возвращается номер строки rowId иначе - */ public long createTodo(String category, String summary, String description) { ContentValues initialValues = createContentValues(category, summary, description); return database.insert(DATABASE_id», т.к. некоторые функции Android следуют этомуTABLE, null, initialValues); } // обновить список public boolean updateTodo(long rowId, String category, String summary, String description) { ContentValues updateValues = createContentValues(category, summary, description); return database.update(DATABASE_id», т.к. некоторые функции Android следуют этомуTABLE, updateValues, KEY_id», т.к. некоторые функции Android следуют этомуROWID

  • "=" + rowId, null) > 0; } // удаляет элемент списка public boolean deleteTodo(long rowId) { return database.delete(DATABASE_id», т.к. некоторые функции Android следуют этомуTABLE, KEY_id», т.к. некоторые функции Android следуют этомуROWID + "=" + rowId, null) > 0; } //возвращает курсор со всеми элементами списка дел //@return курсор с результатами всех записей public Cursor fetchAllTodos() { return database.query(DATABASE_id», т.к. некоторые функции Android следуют этомуTABLE, new String[] { KEY_id», т.к. некоторые функции Android следуют этомуROWID, KEY_id», т.к. некоторые функции Android следуют этомуCATEGORY, KEY_id», т.к. некоторые функции Android следуют этомуSUMMARY, KEY_id», т.к. некоторые функции Android следуют этомуDESCRIPTION }, null, null, null, null, null); } //возвращает курсор, спозиционированный на указанной записи public Cursor fetchTodo(long rowId) throws SQLException {

Cursor mCursor = database.query(true, DATABASE_id», т.к. некоторые функции Android следуют этомуTABLE, new String[] { KEY_id», т.к. некоторые функции Android следуют этомуROWID, KEY_id», т.к. некоторые функции Android следуют этомуCATEGORY, KEY_id», т.к. некоторые функции Android следуют этомуSUMMARY, KEY_id», т.к. некоторые функции Android следуют этомуDESCRIPTION }, KEY_id», т.к. некоторые функции Android следуют этомуROWID + "=" + rowId, null, null, null, null, null); if (mCursor != null) { mCursor.moveToFirst(); } return mCursor; } private ContentValues createContentValues(String category, String summary, String description) { ContentValues values = new ContentValues(); values.put(KEY_id», т.к. некоторые функции Android следуют этомуCATEGORY, category); values.put(KEY_id», т.к. некоторые функции Android следуют этомуSUMMARY, summary); values.put(KEY_id», т.к. некоторые функции Android следуют этомуDESCRIPTION, description); return values; } } Добавим несколько ресурсов, которые мы будет использовать позже, в том числе listmenu.xml (в папке menu), который будет использоваться позже для создания новых дел в списке.

Для списка приоритетов создадим массив строк. Добавьте такой файл priority.xml в папке /res/values. Urgent Reminder Мы также создадим еще один ресурс для строк в нашем приложении – файл strings.xml в /res/values. Hello World, Todo! Todo Currently there are no Todo items maintained Add Item Delete Todo Summary Delete Todo

android:textSize="40px" android:layout_id», т.к. некоторые функции Android следуют этомуmarginTop="6px" android:layout_id», т.к. некоторые функции Android следуют этомуwidth="fill_id», т.к. некоторые функции Android следуют этомуparent" android:textColor="@color/black"> Создатим файл лэйаута «todo_id», т.к. некоторые функции Android следуют этомуedit». Этот лэйаут будет использован дальше для отображения и изменения отдельного элемента списка дел.

Наконец, поменяем код наших активити на следующий ниже. Сперва «TodoOverview.java» package de.vogella.android.todos; import android.app.ListActivity; import android.content.Intent;

import android.database.Cursor; import android.os.Bundle; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import de.vogella.android.todos.database.TodoDbAdapter; public class TodosOverview extends ListActivity { private TodoDbAdapter dbHelper; private static final int ACTIVITY_id», т.к. некоторые функции Android следуют этомуCREATE = 0; private static final int ACTIVITY_id», т.к. некоторые функции Android следуют этомуEDIT = 1; private static final int DELETE_id», т.к. некоторые функции Android следуют этомуID = Menu.FIRST + 1; private Cursor cursor; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.todo_id», т.к. некоторые функции Android следуют этомуlist); this.getListView().setDividerHeight(2); dbHelper = new TodoDbAdapter(this); dbHelper.open(); fillData(); registerForContextMenu(getListView()); } // Создаем меню, основанное на XML-файле @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.listmenu, menu); return true; } // Реакция на выбор меню @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch (item.getItemId()) { case R.id.insert: createTodo(); return true; } return super.onMenuItemSelected(featureId, item); } @Override

SimpleCursorAdapter notes = new SimpleCursorAdapter(this, R.layout.todo_id», т.к. некоторые функции Android следуют этомуrow, cursor, from, to); setListAdapter(notes); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(0, DELETE_id», т.к. некоторые функции Android следуют этомуID, 0, R.string.menu_id», т.к. некоторые функции Android следуют этомуdelete); } @Override protected void onDestroy() { super.onDestroy(); if (dbHelper != null) { dbHelper.close(); } } } И затем «TodoDetails.java» package de.vogella.android.todos; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import de.vogella.android.todos.database.TodoDbAdapter; public class TodoDetails extends Activity { private EditText mTitleText; private EditText mBodyText; private Long mRowId; private TodoDbAdapter mDbHelper; private Spinner mCategory; @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); mDbHelper = new TodoDbAdapter(this); mDbHelper.open(); setContentView(R.layout.todo_id», т.к. некоторые функции Android следуют этомуedit); mCategory = (Spinner) findViewById(R.id.category); mTitleText = (EditText) findViewById(R.id.todo_id», т.к. некоторые функции Android следуют этомуedit_id», т.к. некоторые функции Android следуют этомуsummary); mBodyText = (EditText) findViewById(R.id.todo_id», т.к. некоторые функции Android следуют этомуedit_id», т.к. некоторые функции Android следуют этомуdescription); Button confirmButton = (Button) findViewById(R.id.todo_id», т.к. некоторые функции Android следуют этомуedit_id», т.к. некоторые функции Android следуют этомуbutton); mRowId = null;

Bundle extras = getIntent().getExtras(); mRowId = (bundle == null) ?». null : (Long) bundle .getSerializable(TodoDbAdapter.KEY_id», т.к. некоторые функции Android следуют этомуROWID); if (extras != null) { mRowId = extras.getLong(TodoDbAdapter.KEY_id», т.к. некоторые функции Android следуют этомуROWID); } populateFields(); confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { setResult(RESULT_id», т.к. некоторые функции Android следуют этомуOK); finish(); } }); } private void populateFields() { if (mRowId != null) { Cursor todo = mDbHelper.fetchTodo(mRowId); startManagingCursor(todo); String category = todo.getString(todo .getColumnIndexOrThrow(TodoDbAdapter.KEY_id», т.к. некоторые функции Android следуют этомуCATEGORY)); for (int i=0; i<mCategory.getCount();i++){ String s = (String) mCategory.getItemAtPosition(i); Log.e(null, s +" " + category); if (s.equalsIgnoreCase(category)){ mCategory.setSelection(i); }} mTitleText.setText(todo.getString(todo.getColumnIndexOrThrow(TodoDbAdapter.K EY_id», т.к. некоторые функции Android следуют этомуSUMMARY))); mBodyText.setText(todo.getString(todo.getColumnIndexOrThrow(TodoDbAdapter. KEY_id», т.к. некоторые функции Android следуют этомуDESCRIPTION))); } } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); saveState(); outState.putSerializable(TodoDbAdapter.KEY_id», т.к. некоторые функции Android следуют этомуROWID, mRowId); } @Override protected void onPause() { super.onPause(); saveState(); } @Override protected void onResume() { super.onResume(); populateFields(); } private void saveState() { String category = (String) mCategory.getSelectedItem(); String summary = mTitleText.getText().toString();

соответствующие данные, принадлежащие другому приложению, в том числе данные стандартных БД Android. В общем случае, контент-провайдеры следует создавать только тогда, когда требуется предоставить другим приложениям доступ к данным вашего приложения. В остальных случаях рекомендуется использовать СУБД (SQLite). Тем не менее, иногда контент-провайдеры используются внутри одного приложения для поиска и обработки специфических запросов к данным. Для доступа к данным какого-либо контент-провайдера используется объект класса ContentResolver, который можно получить с помощью метода getContentResolver контекста приложения для связи с поставщиком в качестве клиента: ContentResolver cr = getApplicationContext().getContentResolver(); Объект ContentResolver взаимодействует с объектом контент-провайдера, отправляя ему запросы клиента. Контент-провайдер обрабатывает запросы и возвращает результаты обработки. Контент-провайдеры представляют свои данные потребителям в виде одной или нескольких таблиц подобно таблицам реляционных БД. Каждая строка при этом является отдельным «объектом» со свойствами, указанными в соответствующих именованных полях. Как правило, каждая строка имеет уникальный целочисленный индекс и именем «_id», т.к. некоторые функции Android следуют этомуid», который служит для однозначной идентификации требуемого объекта. Контент-провайдеры, обычно предоставляют минимум два URI для работы с данными: один для запросов, требующих все данные сразу, а другой – для обращения к конкретной «строке». В последнем случае в конце URI добавляется / (который совпадает с индексом «_id», т.к. некоторые функции Android следуют этомуid»). Запросы на получение данных похожи на запросы к БД, при этом используется метод query объекта ContentResolver. Ответ также приходит в виде курсора, «нацеленного» на результирующий набор данных (выбранные строки таблицы): ContentResolver cr = getContentResolver(); // получить данные всех контактов Cursor c = cr.query(ContactsContract.Contacts.CONTENT_id», т.к. некоторые функции Android следуют этомуURI, null, null, null, null); // получить все строки, где третье поле имеет конкретное // значение и отсортировать по пятому полю String where = KEY_id», т.к. некоторые функции Android следуют этомуCOL3 + "=" + requiredValue; String order = KEY_id», т.к. некоторые функции Android следуют этомуCOL5; Cursor someRows = cr.query(MyProvider.CONTENT_id», т.к. некоторые функции Android следуют этомуURI, null, where, null, order); Извлечение данных-результатов запроса с помощью курсора было рассмотрено ранее. Uri myRowUri = cr.insert(SampleProvider.CONTENT_id», т.к. некоторые функции Android следуют этомуURI, newRow); // Массовая вставка: ContentValues[] valueArray = new ContentValues[5]; // здесь заполняем массив

// делаем вставку int count = cr.bulkInsert(MyProvider.CONTENT_id», т.к. некоторые функции Android следуют этомуURI, valueArray); При вставке одного элемента метод insert возвращает URI вставленного элемента, а при массовой вставке возвращается количество вставленных элементов. Пример удаления: ContentResolver cr = getContentResolver(); // удаление конкретной строки cr.delete(myRowUri, null, null); // удаление нескольких строк String where = "_id», т.к. некоторые функции Android следуют этомуid < 5"; cr.delete(MyProvider.CONTENT_id», т.к. некоторые функции Android следуют этомуURI, where, null); Пример изменения: ContentValues newValues = new ContentValues(); newValues.put(COLUMN_id», т.к. некоторые функции Android следуют этомуNAME, newValue); String where = "_id», т.к. некоторые функции Android следуют этомуid < 5"; getContentResolver().update(MyProvider.CONTENT_id», т.к. некоторые функции Android следуют этомуURI, newValues, where, null); Для чтения информации о контактах используется контент-провайдер ContactsContract, точнее, один из его подклассов. Для этой лабораторной работы воспользуемся провайдером ContactsContract.Contacts. Для чтения контактов приложению требуются полномочия READ_id», т.к. некоторые функции Android следуют этомуCONTACTS.

  1. Добавьте несколько контактов в эмуляторе (поскольку требуется только отображаемое имя контакта, остальные поля можно не заполнять :).
  2. Создайте новый проект ContactsSample.
  3. Выведите имена всех контактов (с помощью ListView), используя для получения информации URI ContactsContract.Contacts.CONTENT_id», т.к. некоторые функции Android следуют этомуURI. Необходимое имя поля для привязки адаптера найдите среди статических констант класса ContactsContract.Contacts. Для создания собственного контент-провайдера требуется расширить класс ContentProvider и переопределить метод onCreate, чтобы проинициализировать источник данных, который требуется опубликовать. Остальные методы этого класса будут, по сути, обертками вокруг методов работы с исходным источником данных. Каркас для класса показан ниже: public class NewProvider extends ContentProvider { public final static Uri CONTENT_id», т.к. некоторые функции Android следуют этомуURI=Uri.parse("URI провайдера"); @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Удаление данных return 0; } @Override public String getType(Uri uri) { // Возвращает тип MIME для указанных объектов(объекта) return null;

private static final UriMatcher uriMatcher; // Заполнение UriMatcher'аа // Если URI оканчивается на /stations - это запрос про все станции // Если на stations/[ID] - про конкретную станцию static { uriMatcher = new UriMatcher(UriMatcher.NO_id», т.к. некоторые функции Android следуют этомуMATCH); uriMatcher.addURI("com.example.provider.metropicker", "stations", ALL_id», т.к. некоторые функции Android следуют этомуSTATIONS); uriMatcher.addURI("com.example.provider.metropicker", "stations/#", SINGLE_id», т.к. некоторые функции Android следуют этомуSTATION); } В дальнейшем полученный в запросе к контент-провайдеру URI проверяется в методах класса следующим образом: @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { switch (uriMatcher.match(uri)) { case ALL_id», т.к. некоторые функции Android следуют этомуSTATIONS: // Вернуть курсор, указывающий на выборку со // всеми станциями case SINGLE_id», т.к. некоторые функции Android следуют этомуSTATION: // Вытащить ID станции из URI: String _id», т.к. некоторые функции Android следуют этомуid = uri.getPathSegments().get(1); // Вернуть курсор, указывающий на выборку с одной // станцией. } return null; } При наполнении объекта UriMatcher шаблонами могут применять в «#» и «*» в качестве специальных символов: # в шаблоне совпадает с любым числом, а * - с любым текстом. Кроме уникальных URI, используемым создаваемым контент-провайдером, для определения клиентами типа возвращаемых по запросу данных используются уникальные типы MIME. Метод getType класса ContentProvider обычно возвращает один тип данных для массовой выборки, а другой – для одиночных записей. В нашем случае это могло бы выглядеть так: @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case ALL_id», т.к. некоторые функции Android следуют этомуSTATIONS: return "vnd.com.example.cursor.dir/station"; case SINGLE_id», т.к. некоторые функции Android следуют этомуSTATION: return "vnd.com.example.cursor.item/station"; default: throw new IllegalArgumentException("Unsupported URI: " + uri); } }

Для того, что бы Android знал о существовании и мог использовать (через ContentResolver) ваш контент-провайдер, его нужно описать в Манифесте приложения. Минимальное описание выглядит так: В данном случае указаны только обязательные атрибуты элемента : имя класса контент-провайдера и его область ответственности. Варианты Задание : Создать приложение с использованием базы данных и с использованием контент провайдера. № Название базы данных 1 Мебель 2 Украшение 3 Журнал 4 Растение 5 Техника 6 Книга 7 Компьютер 8 Район 9 Продукт 10 Устройство 11 Спорт 12 Камни 13 Обуви 14 Птицы 15 Библиотеки 16 Футболисты 17 Животные 18 Фрукты 19 Посуды 20 Телефоны 21 напиток, кисель 22 Доктор 23 Школы 24 Больница 25 Страны 26 Парфюмерия 27 Университеты