Главная » Разработка для Android » Вставка новых строк

0

Для  создания  новой строки  понадобится объект ContentValues, точ- нее, его метод put, чтобы обеспечить  данными  каждый  столбец. Вставьте новую строку, передавая  в метод insert,  вызванный в контексте  нужной нам базы данных, имя таблицы и объект ContentValues, как показано в ли- стинге 7.6.

Листинг 7.6. в базу данных

// Создайте новую строку со значениями для вставки. ContentValues newValues = new ContentValues();

// Задайте значения для каждой строки. newValues.put(COLUMN_NAME, newValue);

[ … Повторите для каждого столбца … ]

// Вставьте строку в вашу базу данных. myDatabase.insert(DATABASE_TABLE, null, newValues);

Обновление строк в таблице

Обновление строк также происходит с помощью класса ContentValues. Создайте новый объект ContentValues, используя метод put для вставки

значений в каждый столбец, который вы хотите обновить. Вызовите метод

update в контексте базы данных, передайте ему имя таблицы, обновленный объект ContentValues и оператор WHERE, указывающий на строку (стро- ки), которую нужно обновить. Все это показано в листинге 7.7.

Листинг 7.7. Обновление строки в базе данных

// Определите содержимое обновленной строки. ContentValues updatedValues = new ContentValues();

// Назначьте значения для каждой строки. newValues.put(COLUMN_NAME, newValue);

[ … Повторите для каждого столбца … ] String where = KEY_ID + "=" + rowId;

// Обновите строку с указанным индексом, используя новые значения. myDatabase.update(DATABASE_TABLE, newValues, where, null);

Удаление строк из таблицы

Чтобы удалить строку, просто вызовите  метод delete в контексте  базы данных, указав имя таблицы и оператор WHERE. В результате вы получите строки, которые хотите удалить, как показано в листинге 7.8.

Листинг 7.8. Удаление  строки из базы данных

myDatabase.delete(DATABASE_TABLE, KEY_ID + "=" + rowId, null);

Сохранение пунктов списка в приложении To-Do List

В главе 6 вы улучшили пример To-Do List, добавив сохранение состояния пользовательского интерфейса Активностей между сессиями.  Но это была только половина работы. В следующем примере1 вы создадите базу данных для сохранения  пунктов списка.

1. Начните  с создания  нового класса ToDoDBAdapter. Он нужен для взаимодействия с вашей базой данных. Создайте приватные поля для хранения объекта SQLiteDatabase, а также Context, принадлежащего приложению. Добавьте конструктор, который принимает Context в ка- честве параметра и оформляет статические поля для имени и версии базы данных, а также для имени таблицы, в которой будут храниться пункты из списка.

package com.paad.todolist;

import android.content.ContentValues;

import android.content.Context;

import android.database.Cursor;

import android.database.SQLException;

import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log;

public class ToDoDBAdapter {

private static final String DATABASE_NAME = "todoList.db"; private static final String DATABASE_TABLE = "todoItems"; private static final int DATABASE_VERSION = 1;

private SQLiteDatabase db;

private final Context context;

public ToDoDBAdapter(Context _context) {

this.context = _context;

}

}

1     Все фрагменты  кода в этом примере  — часть проекта Todo List из главы 7, их можно за- грузить с сайта Wrox.com.

2. Создайте  публичные  вспомогательные поля, которые  определяют имена столбцов. Это упростит нахождение нужных столбцов при из- влечении данных из результирующих Курсоров:

public static final String KEY_ID = "_id";

public static final String KEY_TASK = "task";

public static final String KEY_CREATION_DATE = "creation_date";

3. Создайте  новый класс toDoDBOpenHelper внутри ToDoDBAdapter, наследующий   SQLiteOpenHelper. Он нужен для упрощения  работы с версиями вашей базы данных. Внутри него переопределите методы onCreate и onUpgrade для управления логикой создания и обновления базы данных.

private static class toDoDBOpenHelper extends SQLiteOpenHelper {

public toDoDBOpenHelper(Context context, String name, CursorFactory factory, int version) {

super(context, name, factory, version);

}

// Конструкция на языке SQL для создания новой базы данных. private static final String DATABASE_CREATE = "create table " +

DATABASE_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " +

KEY_TASK + " text not null, " + KEY_CREATION_DATE + " long);";

@Override

public void onCreate(SQLiteDatabase _db) {

_db.execSQL(DATABASE_CREATE);

}

@Override

public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _

newVersion) {

Log.w("TaskDBAdapter", "Upgrading from version " +

_oldVersion + " to " +

_newVersion + ", which will destroy all old data");

// Удалите старую таблицу.

_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);

// Создайте новую. onCreate(_db);

}

}

4. Добавьте приватное  поле для класса ToDoDBAdapter, которое будет хранить экземпляр класса toDoDBOpenHelper, созданного в предыду- щем пункте. Инициализируйте его внутри конструктора.

private toDoDBOpenHelper dbHelper;

public ToDoDBAdapter(Context _context) {

this.context = _context;

dbHelper = new toDoDBOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION);

}

5. В этом же классе создайте методы open и close, которые икнапсулиру- ют логику, отвечающую за открытие и закрытие базы данных. Начните с метода close: внутри него просто вызывается одноименный метод из объекта базы данных.

public void close() {

db.close();

}

6. В методе open должен  использоваться класс toDoDBOpenHelper.

Вызовите метод getWritableDatabase, чтобы позволить этому вспомо-

гательному классу обрабатывать создание базы данных и проверку ее версий. Предусмотрите выброс исключения при данном вызове, чтобы открыть  базу данных в режиме  для чтения,  если режим для записи недоступен.

public void open() throws SQLiteException {

try {

db = dbHelper.getWritableDatabase();

} catch (SQLiteException ex) {

db = dbHelper.getReadableDatabase();

}

}

7. Внесите строго типизированные методы для добавления, удаления и обновления элементов списка.

// Вставка нового элемента

public long insertTask(ToDoItem _task) {

// Создайте новую строку со значениями, которые нужно вставить. ContentValues newTaskValues = new ContentValues();

// Присвойте значения для каждой строки. newTaskValues.put(KEY_TASK, _task.getTask()); newTaskValues.put(KEY_CREATION_DATE, _task.getCreated().getTime());

// Вставьте строку.

return db.insert(DATABASE_TABLE, null, newTaskValues);

}

// Удаление элемента с конкретным индексом public boolean removeTask(long _rowIndex) {

return db.delete(DATABASE_TABLE, KEY_ID + "=" + _rowIndex, null) > 0;

}

// Обновление элемента

public boolean updateTask(long _rowIndex, String _task) { ContentValues newValue = new ContentValues(); newValue.put(KEY_TASK, _task);

return db.update(DATABASE_TABLE, newValue, KEY_ID + "=" + _rowIndex, null) > 0;

}

8. Добавьте вспомогательные методы для обработки запросов. Потребу- ются три метода: один возвращает  все элементы, другой — конкрет- ную строку в виде курсора, а третий — объект, приведенный к типу ToDoItem.

public Cursor getAllToDoItemsCursor() {

return db.query(DATABASE_TABLE,

new String[] { KEY_ID, KEY_TASK, KEY_CREATION_DATE}, null, null, null, null, null);

}

public Cursor setCursorToToDoItem(long _rowIndex) throws SQLException { Cursor result = db.query(true, DATABASE_TABLE,

new String[] {KEY_ID, KEY_TASK},

KEY_ID + "=" + _rowIndex, null, null, null, null, null);

if ((result.getCount() == 0) || !result.moveToFirst()) {

throw new SQLException("No to do items found for row: " + _rowIndex);

}

return result;

}

public ToDoItem getToDoItem(long _rowIndex) throws SQLException { Cursor cursor = db.query(true, DATABASE_TABLE,

new String[] {KEY_ID, KEY_TASK},

KEY_ID + "=" + _rowIndex, null, null, null, null, null);

if ((cursor.getCount() == 0) || !cursor.moveToFirst()) {

throw new SQLException("No to do item found for row: " + _rowIndex);

}

String task = cursor.getString(TASK_COLUMN);

long created = cursor.getLong(CREATION_DATE_COLUMN);

ToDoItem result = new ToDoItem(task, new Date(created));

return result;

}

9. На этом вспомогательный класс для работы с базой данных закон- чен. Вернитесь  к Активности ToDoList и отредактируйте ее с учетом поддержки  сохранения  массива с заданиями.  Начните  с изменения метода onCreate, создав экземпляр класса toDoDBAdapter и открыв соединение с базой данных. Разместите также вызов метода-заглушки populateTodoList.

ToDoDBAdapter toDoDBAdapter;

public void onCreate(Bundle icicle) {

[ … ранее написанный код в методе onCreate … ]

toDoDBAdapter = new ToDoDBAdapter(this);

// Откройте или создайте базу данных

toDoDBAdapter.open();

populateTodoList();

}

private void populateTodoList() { }

10.   Создайте новое поле для хранения экземпляра Курсора, указывающего на все элементы в базе данных. Отредактируйте метод populateTodoList, используя экземпляр класса toDoDBAdapter, чтобы выполнять за- просы к базе данных. Вызовите  метод startManagingCursor, чтобы позволить Активности управлять объектом Cursor. Следует также вы- звать метод updateArray — он понадобится для повторного заполнения массива со списком заданий с помощью Курсора.

Cursor toDoListCursor;

private void populateTodoList() {

// Получите все элементы из базы данных.

toDoListCursor = toDoDBAdapter. getAllToDoItemsCursor();

startManagingCursor(toDoListCursor);

// Обновите массив. updateArray();

}

private void updateArray() { }

11. Реализуйте метод updateArray, который  будет обновлять массив со списком текущих заданий. Вызовите requery в контексте объекта Cursor,  чтобы убедиться  в его полной актуальности, затем очистите массив и пройдитесь по результирующему набору данных. Когда обнов- ление закончится,  вызовите  метод notifyDataSetChanged из объекта ArrayAdapter.

private void updateArray() {

toDoListCursor.requery();

todoItems.clear();

if (toDoListCursor.moveToFirst())

do {

String task = toDoListCursor.getString(ToDoDBAdapter.TASK_COLUMN);

long created = toDoListCursor.getLong(ToDoDBAdapter.CREATION_DATE_ COLUMN);

ToDoItem newItem = new ToDoItem(task, new Date(created));

todoItems.add(0, newItem);

} while(toDoListCursor.moveToNext());

aa.notifyDataSetChanged();

}

12. Чтобы свести все воедино, отредактируйте класс OnKeyListener, свя- занный с полем ввода в методе onCreate, и поправьте метод removeItem. Вместо изменения массива со списком заданий напрямую эти методы должны  использовать toDoDBAdapter, чтобы добавлять  и удалять элементы из базы данных.

12.1.Начните с OnKeyListener. Вставьте новый элемент в базу данных и обновите массив.

public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main);

myListView = (ListView)findViewById(R.id.myListView);

myEditText = (EditText)findViewById(R.id.myEditText);

todoItems = new ArrayList<ToDoItem>();

int resID = R.layout.todolist_item;

aa = new ToDoItemAdapter(this, resID, todoItems);

myListView.setAdapter(aa);

myEditText.setOnKeyListener(new OnKeyListener() {

public boolean onKey(View v, int keyCode, KeyEvent event) {

if (event.getAction() == KeyEvent.ACTION_DOWN)

if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {

ToDoItem newItem = new ToDoItem(myEditText.getText(). toString());

toDoDBAdapter.insertTask(newItem); updateArray(); myEditText.setText(""); aa.notifyDataSetChanged(); cancelAdd();

return true;

}

});

}

return false;

registerForContextMenu(myListView);

restoreUIState();

toDoDBAdapter = new ToDoDBAdapter(this);

// Откройте или создайте базу данных toDoDBAdapter.open();

populateTodoList();

}

12.2.Отредактируйте метод removeItem, чтобы удалять  элементы  из базы данных и обновлять массив.

private void removeItem(int _index) {

// Элементы добавляются в объект ListView в обратном порядке, поэтому инвертируйте индекс.

toDoDBAdapter.removeTask(todoItems.size()-_index);

updateArray();

}

13. Финальный шаг: переопределите метод onDestroy, принадлежащий вашей Активности, чтобы закрывать соединение  с базой данных при выходе:

@Override

public void onDestroy() {

super.onDestroy();

// Закройте базу данных toDoDBAdapter.close();

}

Теперь задания из списка будут сохраняться между сессиями. Для дальней- шего улучшения вы можете заменить ArrayAdapter на SimpleCursorAdapter — это обеспечит динамическое  обновление  ListView  при изменениях в базе данных.

Поскольку вы используете приватную  базу данных,  ваши задания не доступны  для других приложений. Чтобы  обеспечить  доступ, нужно воспользоваться Источниками данных. Этим вы и займетесь  в следующем разделе.

Источник: Майер P. Android 2 : программирование приложений для планшетных компьютеров и смартфонов : [пер. с англ. ] / Рето Майер. — М. : Эксмо, 2011. — 672 с. — (Мировой компьютерный бестселлер).

По теме:

  • Комментарии