В Android-приложениях есть возможность хранить большой объем данных в собственной, скрытой от посторонних глаз БД. Ты удивишься, насколько это может быть полезно и, самое главное, легко!
 

Приложение или браузер

Мобильные приложения становятся логичным развитием интернет-сайтов. В целом они эффективней используют ресурсы устройства, да и возможностей по работе с данными тут больше. Часто веб-разработчики сталкиваются с естественными ограничениями мобильных устройств — отсутствием флеша, тормозами страницы из-за перегруженности и другими. И никто не будет спорить, что работать с картами или почтой удобней в нативных программах, а не в браузере.

Использование базы данных поможет сохранить все необходимые пользователю данные, и это очень круто. Все возможности приложения будут доступны, даже если пользователь уедет в тайгу, где интернета никогда и не было. Когда-то давно, целых полтора года назад, наш журнал уже делал обзор способов сохранения данных в Android, но база данных заслуживает отдельной статьи.

 

Кешируем всё

В Android из коробки база данных присутствует в виде библиотеки SQLite, которую даже не нужно как-то подключать или запрашивать на нее разрешение у пользователя. Чтобы понять, насколько она полезна, напишем полноценное приложение, которое будет загружать данные из интернета и кешировать их, а затем выдавать их в любых условиях: в дождь, мороз и дисконнект.

SQLite — легковесный фреймворк, который, с одной стороны, дает по максимуму использовать возможности SQL, с другой — бережно относится к ресурсам устройства. Его недостатки малокритичны для мобильной разработки: к примеру, нет индексов для LIKE-запросов и есть лимиты на размер базы данных.

 

Сериализация и JSON

Самое время поговорить о контенте: в принципе, нам абсолютно неважно, что кешировать. Тем не менее хранить в БД все подряд не стоит: если это будут какие-то разовые записи или отметки о состоянии Activity, лучше использовать SharedPreferences. Как и во «взрослых» системах, база данных предназначена для сохранения большого объема структурированной информации: каталога товаров, списка задач, новостных блоков и так далее.

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

На смену XML пришел формат JSON, который, пожалуй, уже стал стандартом. Он не только прост в парсинге, но и удобен для веб-разработчиков: например, он легко разбирается с помощью JavaScript. Формат JSON довольно прост и легко читается как приложениями, так и просто глазами. Для примера я взял список пользователей с несколькими параметрами — имя, описание, собственный идентификатор и картинка-аватар.

Рис. 1. Как парсить JSON
Рис. 1. Как парсить JSON
{
    "name":"John",
    "description":"desc #1",
    "id":3137,
    "image":"link_to_image.url"
}

Такой массив данных довольно легко раскладывается в Java-объект. Создать класс с нужным содержанием можно руками или воспользоваться конвертерами, которые ищутся по запросу json to java. Такой конвертер самостоятельно разберет поля и добавит аннотации с указанием полей.

@SerializedName("id")
@Expose
public Integer id;
@SerializedName("name")
@Expose
public String name;
@SerializedName("description")
@Expose
public String description;
@SerializedName("image")
@Expose
public String urlImage;
...

Загрузив JSON в приложение, его нужно будет разложить по полям в подготовленный Java-объект. Для этого тоже есть готовые решения. Мне нравятся библиотека Retrofit и конвертер Gson Converter, о которых мы не раз писали. Если нет каких-то экзотических требований к сетевым запросам — Retrofit тебе однозначно подойдет.

 

CRUD и DAO

Принцип построения таблиц и связей между ними ничем не отличается от классического SQL. Под созданный JSON я решил выделить две таблицы: в одной будет вся текстовая информация, а в другой набор изображений. Выделять изображения в отдельную таблицу есть смысл для экономии памяти — несколько пользователей могут иметь одинаковые аватарки, тогда их не придется дублировать.

Рис. 2. Схема базы данных
Рис. 2. Схема базы данных

При работе с БД удобно пользоваться несколькими паттернами, которые помогают не изобретать велосипеды и при этом реализовать всё, что нужно. Базовый набор запросов содержится в акрониме CRUD — create, read, update и delete. А еще в ООП есть свои шаблоны кода, которые тоже придуманы не зря. Все CRUD-запросы рекомендуется реализовать через паттерн DAO — data access object. Он подразумевает под собой создание интерфейса, в котором будут обозначены необходимые методы.

public interface DAO {
    void insertPerson(ContactJson json);
    ContactJson selectPerson(int id);
    void updatePerson(ContactJson json, int id);
    void deletePerson(int id);
}

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

 

SQLiteOpenHelper

Язык SQL-запросов ближе к процедурному программированию, чем к ООП, поэтому для работы с БД в Android создан отдельный класс SQLiteOpenHelper. Он позволяет общаться с базой данных на привычном для Java-разработчика языке методов и классов. Как обычно, создаем свой объект, дополняя его необходимыми данными — названием и версией БД.

public class DummySQLite extends SQLiteOpenHelper {
    public DummySQLite(Context context, ...) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

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

private static final int DATABASE_VERSION=1;
private static final String DATABASE_NAME="DummyDB";
private static final String TABLE_USERS="users";
private static final String USER_ID="idUser";
private static final String USER_NAME="name";
...

И хотя принципы работы с БД максимально приближены к логике ООП-разработки, от синтаксиса SQL никуда не денешься. Если у тебя есть пробелы в знаниях — почитай какой-нибудь мануал для начинающих. В большинстве случаев базовых знаний будет достаточно.

Класс SQLiteOpenHelper требует обязательного переопределения методов, используемых при инициализации, — методов создания, открытия и обновления базы данных. В onCreate необходимо задать команды для создания таблиц внутри базы данных, он будет вызван системой самостоятельно при первоначальной инициализации базы данных.

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
    String CREATE_USERS_TABLE = "CREATE TABLE " + TABLE_USERS + " (" +
        USER_ID + " INTEGER PRIMARY KEY," + USER_NAME + " TEXT," +
        USER_DESCR + " TEXT, " + sqLiteDatabase.execSQL(CREATE_USERS_TABLE);
    ...
}

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

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_IMAGES);
    ...
}

Продолжение статьи доступно только подписчикам

Вариант 1. Оформи подписку на «Хакер», чтобы читать все статьи на сайте

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

Вариант 2. Купи одну статью

Заинтересовала статья, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для статей, опубликованных более двух месяцев назад.


Комментарии

Подпишитесь на ][, чтобы участвовать в обсуждении

Обсуждение этой статьи доступно только нашим подписчикам. Вы можете войти в свой аккаунт или зарегистрироваться и оплатить подписку, чтобы свободно участвовать в обсуждении.

Check Also

Страдания с ReactOS. Почему в заменителе Windows работают трояны, но не работает Word

Сегодня в нашей кунсткамере демонстрируется необычайный организм — двадцатилетний зародыш …