Опубликовано: 25 Октября 2017
(Демо приложение №5)
Сохранение настроек. Модуль App Preference

В этом уроке мы рассмотрим необходимость сохранения небольших наборов простых данных между перезапусками приложения. Для этого воспользуемся модулем App Preference.

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

Описание модуля

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

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

При помощи App Preference вы просто вызываете функцию сохранить значение, или функцию загрузить значение, что может быть проще? Значение сохраняется в операционной системе с привязкой к имени пакета вашего приложения, который прописан в манифест файле, и ключу который вы задаете для хранения переменной. Таким образом если в вашем пакете например есть сервис-приложение и ui-приложение то вы можете обращаться к одним данным из ваших приложений.

Еще одна приятная вещь: вы можете создавать обработчики на событие изменение переменной хранящейся с заданным ключем.

Сохранение выбраного стиля

Теперь зная что из себя представляет App Preferences давайте воспользуемся этим модулем и станем сохранять текущий стиль циферблата между перезапусками.

Для использования интерфейса этого модуля включаем следующий заголовочный файл

#include <app_preference.h>

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

#define KEY_STYLE_INDEX "key.style.index"

static void
style_index_save(int style_index)
{
   preference_set_int(KEY_STYLE_INDEX, style_index);
}

Как видите мы определили ключ "key.style.index" для храниния нашего значения индекса стиля.

Для сохранинея значений предусмотрено 4 функции используемых для сохранения значений разных типов.

preference_set_boolean(const char *key, bool value);
preference_set_int(const char *key, int value);
preference_set_double(const char *key, double value);
preference_set_string(const char *key, const char *value);

Мы использовали функцию для сохранения целочисленного значения.

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

Теперь реализуем функцию для загрузки нашего индекса стиля из системы.

static int
style_index_load()
{
   int style_index = 0;
   bool is_existing = false;

   preference_is_existing(KEY_STYLE_INDEX, &is_existing);
   if (is_existing)
     preference_get_int(KEY_STYLE_INDEX, &style_index);

   return style_index;
}

Для загрузки значений также предусмотренно 4 функции для разных типов

preference_get_boolean(const char *key, bool *value);
preference_get_int(const char *key, int *value);
preference_get_double(const char *key, double *value);
preference_get_string(const char *key, char **value);

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

preference_is_existing(const char *key, bool *existing);

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

Пришло время задействовать наши функции.

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

static void
down_cb(void *data, Evas *evas, Evas_Object *obj, void *event)
{
   ...

   int styles_count = EINA_C_ARRAY_LENGTH(styles);
   ui->style_index = (ui->style_index + 1) % styles_count;
   style_index_save(ui->style_index);

   ...
}

Теперь добавим загрузку сохраненного стиля во время создания приложения. Для этого добавим следующую строку перед созданием окна и всех графических компонентов.

static bool
_app_create(int width, int height, void *data)
{
   UIData *ui = data;
   ui->style_index = style_index_load();

   ...
}

Давайте посмотрим как это работает в нашем приложении.

Как видно при перезагрузке циферблата выбранный стиль сохраняется за счет того что мы воспользовались App Preference.

Дополнительные функции модуля

Иногда существует необходимость получить уведомление о том что значение хранимое в App Preference изменилось, для этого вам необходимо всего лишь воспользоваться следующей функцией и реализовать собственную функцию-обработчик.

preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data);

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

Важно:

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

Поэтому если мы советуем перед вызовом регистрации обработчика сначала проверить существуют ли данные с заданным ключем, и если нет, сохранить некое нулевое значение функцией preference_set_int() или любой другой подобной.

Для удаления обработчика можно вызвать следующую функцию.

preference_unset_changed_cb(const char *key);

Важно:

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

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

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

preference_remove(const char *key);

Также есть возможность стереть все пары ключ-значение вызовом следующей функции.

preference_remove_all();

На этом мы заканчиваем наше демо-приложение 5. Проект с исходным кодом вы можете скачать здесь WearLesson030.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *