У цьому уроці ми розглянемо необхідність зберігати невеликі набори простих даних між перезапусками додатку. Для цього буде використано App Preference модуль.
З допомогою App Preference зберігається інформація про поточний вибраний стиль циферблату, таким чином, при зміні циферблатів і встановленні вашого назад, додаток буде завантажуватись з стилем, який було встановлені під час останнього сеансу роботи циферблату.
Як вже було сказано, в основному цей модуль використовується для збереження налаштувань додатку, що є невеликий набір даних. Загалом, можна зберігати будь-які дані, якщо виникне така необхідність.
Таким чином, якщо у вас є декілька змінних, значення яких ви хочете зберегти до наступного запуску додатку, то вам не потрібно відкривати файл, зберігати туди ці величини, а потім відкривати їх і зчитувати чи використовувати бази даних. У обох випадках вам доведеться реалізувати деякий функціонал, відповідно витратити на це час. За допомогою App Preference ви просто викликаєте функцію аби зберегти чи завантажити значення. Що може бути простіше? Значення зберігаються в операційній системі з прив’язкою до імені пакету вашого додатку, який прописано в маніфест файлі, і ключу, який ви задаєте для збереження змінної. Таким чином, якщо у вашому пакеті, наприклад, є сервіс-додаток і ui додаток, то ви можете звертатись до одних і тих же даних з обох цих додатків.
Ще одна перевага використання App Preference є можливість створювати обробник на подію зміни змінної, що зберігається за певним ключем.
Тепер, знаючи, що з себе представляє 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);
Важливо:
Коли ви встановлюєте обробник на зміну значення, пам’ятайте, що для кожного ключа може існувати тільки один обробник.
Тобто, два обробники на один ключ зареєструвати не можна. Бо в такому разі, при виклику функції вдруге, перший обробник відпаде, а буде використовуватись останній зареєстрований.
Також може виникнути необхідність стерти дані разом з ключем, для цього передбачена наступна функція:
preference_remove(const char *key);
Також є можливість стерти всі пари ключ-значення, викликом наступної функції:
preference_remove_all();
На цьому ми закінчуємо демо-додаток номер 5. Проект з початковим кодом можна скачати тут WearLesson030.