В этом уроке мы рассмотрим необходимость сохранения небольших наборов простых данных между перезапусками приложения. Для этого воспользуемся модулем 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.