на экране с подробной информацией должен присутствовать некоторый
признак, подсказывающий, что книга уже имеется в закладках;
пользователь должен иметь возможность удалить выбранную им книгу
из закладок.
Первые два пункта в этом списке будут реализованы в Android и iOS совер
-
шенно по-разному. Однако, поскольку мы используем архитектуру MVC, ос
-
новные отличия будут сосредоточены на уровне Model. Уровни View и Control
-
ler (то есть последние два элемента в этом списке требований) будут иметь
архитектурно схожую реализацию.
А теперь приступим к созданию слоя хранения данных.
Android
Как уже не раз упоминалось, в Android есть несколько способов хранения
данных, и на момент написания этой книги компания Google предлагала ис
-
пользовать библиотеку Room. Однако мы используем SQLite по нескольким
причинам, наиболее важной из которых являются зрелость и распространен
-
ность SQL, фактически ставшего золотым стандартом. SQLite дает возмож
-
ность хранить данные только на локальном устройстве, но поддерживает тот
же базовый синтаксис, правила и операции, что и все основные базы данных
SQL, такие как PostgreSql, MySql и MSSql. Конечно, вы можете поэксперимен
-
тировать с другими подходами, такими как Room. Также популярностью поль
-
зуется библиотека Realm, которая к тому же предлагает преимущество кросс-
платформенности.
Независимо от того, какое решение примете вы, в этой книге мы посмотрим,
как создать слой хранения данных на основе SQLite.
Прежде всего так же, как при использовании любой другой системы управ
-
ления реляционными базами данных, нам нужна хотя бы одна таблица. В на
-
шем примере мы используем три таблицы: одну для экземпляров
Book
, одну
для хранения имен авторов (в виде строки) и одну для связки первых двух.
Таблицы, предназначенные для связки, иногда называют сквозными таблица
-
ми, таблицами мостов, сводными таблицами или таблицами соединений. Это
очень распространенная парадигма, поэтому мы посчитали, что ее примене
-
ние послужит отличным и простым примером использования SQL.
Далее мы используем стандартный синтаксис SQL «создания таблиц». Более
подробную информацию о каждой инструкции и ключевом слове вы найдете
в документации разработчика, однако мы постараемся дать вам достаточно
информации, чтобы вы могли приступить к работе.
CREATE TABLE IF NOT EXISTS BOOKS (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
TITLE TEXT,
ISBN TEXT,
PAGECOUNT INTEGER,
IS_FICTION INTEGER);
Запись книг в хранилище
323
CREATE TABLE IF NOT EXISTS AUTHORS (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
NAME TEXT);
CREATE TABLE IF NOT EXISTS BOOK_AUTHORS (
BOOK_ID INTEGER REFERENCES BOOKS(ID),
AUTHOR_ID INTEGER REFERENCES AUTHORS(ID))
Нам нужно, чтобы при первом запуске приложение создавало эти три табли
-
цы, чтобы сразу же иметь к ним доступ. Рассказывая о
SqliteOpenHelper
в гла
-
ве 7, мы говорили, что эту операцию можно выполнить в переопределенном
методе
onCreate
. Он вызывается только один раз – при первом запуске прило
-
жения после установки. Обратите внимание, что он не будет вызван, пока вы
в первый раз не используете подкласс для получения экземпляра базы данных
с по мощью
getReadableDatabase
или
getWritableDatabase
. Мы сами всегда предпо
-
читаем последний из них, потому что получаем возможность обновить храни
-
лище данных.
Вот как это может выглядеть:
Java
public class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(BOOKS_CREATE_TABLE);
database.execSQL(AUTHORS_CREATE_TABLE);
database.execSQL(BRIDGE_CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase database, int i, int i1) {
// ничего не делает
}
public static final String BOOKS_TABLE_NAME = "BOOKS";
public static final String BOOKS_COLUMN_TITLE = "TITLE";
public static final String BOOKS_COLUMN_ISBN = "ISBN";
public static final String BOOKS_COLUMN_PAGECOUNT = "PAGECOUNT";
public static final String BOOKS_COLUMN_ISFICTION = "ISFICTION";
public static final String AUTHORS_TABLE_NAME = "AUTHORS";
public static final String AUTHORS_COLUMN_ID = "ID";
public static final String AUTHORS_COLUMN_NAME = "NAME";
public static final String BRIDGE_TABLE_NAME = "BOOK_AUTHOR_BRIDGE";
public static final String BRIDGE_COLUMN_BOOK_ID = "BOOK_ID";
public static final String BRIDGE_COLUMN_AUTHOR_ID = "AUTHOR_ID";
public static final String BOOKS_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " +
324
Сохранность данных
BOOKS_TABLE_NAME +
" (" +
BOOKS_COLUMN_TITLE + " TEXT," +
BOOKS_COLUMN_ISBN + " TEXT," +
BOOKS_COLUMN_PAGECOUNT + " INTEGER," +
BOOKS_COLUMN_ISFICTION + " INTEGER);";
public static final String AUTHORS_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " +
AUTHORS_TABLE_NAME +
" (" +
AUTHORS_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
AUTHORS_COLUMN_NAME + " TEXT)";
public static final String BRIDGE_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " +
BRIDGE_TABLE_NAME +
" (" +
BRIDGE_COLUMN_BOOK_ID + " INTEGER REFERENCES BOOKS," +
BRIDGE_COLUMN_AUTHOR_ID + " INTEGER REFERENCES AUTHORS)";
}
Kotlin
class DbHelper(context: Context, name: String, factory: SQLiteDatabase.CursorFactory,
version: Int) :
SQLiteOpenHelper(context, name, factory, version) {
override fun onCreate(database: SQLiteDatabase) {
database.execSQL(BOOKS_CREATE_TABLE)
database.execSQL(AUTHORS_CREATE_TABLE)
database.execSQL(BRIDGE_CREATE_TABLE)
}
override fun onUpgrade(database: SQLiteDatabase, i: Int, i1: Int) {
// ничего не делает
}
companion object {
const val BOOKS_TABLE_NAME = "BOOKS"
const val BOOKS_COLUMN_TITLE = "TITLE"
const val BOOKS_COLUMN_ISBN = "ISBN"
const val BOOKS_COLUMN_PAGECOUNT = "PAGECOUNT"
const val BOOKS_COLUMN_ISFICTION = "ISFICTION"
const val AUTHORS_TABLE_NAME = "AUTHORS"
const val AUTHORS_COLUMN_ID = "ID"
const val AUTHORS_COLUMN_NAME = "NAME"
const val BRIDGE_TABLE_NAME = "BOOK_AUTHOR_BRIDGE"
const val BRIDGE_COLUMN_BOOK_ID = "BOOK_ID"
const val BRIDGE_COLUMN_AUTHOR_ID = "AUTHOR_ID"
const val BOOKS_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + BOOKS_TABLE_NAME +
" (" +
BOOKS_COLUMN_TITLE + " TEXT," +
BOOKS_COLUMN_ISBN + " TEXT," +
BOOKS_COLUMN_PAGECOUNT + " INTEGER," +
Запись книг в хранилище
325
BOOKS_COLUMN_ISFICTION + " INTEGER);"
const val AUTHORS_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + AUTHORS_TABLE_NAME +
" (" + AUTHORS_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
AUTHORS_COLUMN_NAME + " TEXT)"
const val BRIDGE_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + BRIDGE_TABLE_NAME +
" (" +
BRIDGE_COLUMN_BOOK_ID + " INTEGER REFERENCES BOOKS," +
BRIDGE_COLUMN_AUTHOR_ID + " INTEGER REFERENCES AUTHORS)"
}
}
Итак, у нас есть новенькая база данных, еще пахнущая свежей краской, но
она пустая – все наши данные все еще находятся в
Do'stlaringiz bilan baham: |