În Tips & Tricks

Persistarea datelor simple între instanțele unei aplicații

Persitarea datelor simple

De cele mai multe ori, atunci când folosim o aplicație, o serie de informații sunt memorate de aceasta între rulări, chiar dacă închidem aplicația sau telefonul. În general, aceste informații sunt preferințe ale utilizatorului, dar pot fi și date care țin de funcționarea internă a aplicației și sunt transparente pentru acesta. Astfel de informații ajută la îmbunătățirea experienței utilizatorului și la personalizarea ei. Închipuiți-vă că ar trebui să introduceți parola contului de fiecare dată când porniți aplicația de Facebook sau e-mail.

Shared Preferences

Cel mai convenabil mod în care putem persista o informație între instanțele unei aplicații este prin intermediul perechilor cheie-valoare (key-value pairs). Android oferă un API pentru a putea lucra cu un set restrâns de astfel de perechi prin intermediul clasei SharedPreferences. Aceasta oferă un framework generic care permite scrierea și citirea de astfel de perechi, rezumându-se însă doar la tipurile primitive.

Un obiect de tipul SharedPreferences va accesa un fișier care conține acele valori și va oferi metode simple pentru operațiunile de bază. Putem avea însă mai multe fișiere de valori, fiecare dintre ele fiind administrat de acest framework și poate fi privat sau partajat. Din acest motiv, accesul la ele nu poate fi făcut direct, ci doar prin intermediul unui handle. Acesta poate fi obținut în două moduri:

1.getSharedPreferences(<file>, <mode>)

Util în cazul în care avem mai multe fișiere de valori, numele fișierului dorit fiind specificat de primul parametru. Al doilea parametru determină modul în care va fi folosit acel fișier, privat sau partajat. Acesta este o constantă întreagă și, pentru a reține valoarea ei, o putem accesa din cadrul clasei Context. De exemplu:

Context.MODE_PRIVATE

Iată mai jos un exemplu de acces la un fișier de valori:

Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(
                  getString(R.string.preference_file_key), 
Context.MODE_PRIVATE);

2. getPreferences()

Această metodă se poate folosi doar dintr-o clasă Activity și este utilă dacă vrem să folosim doar fișierul dedicat respectivei activități (un nume de fișier nu este necesar).

SharedPreferences sharedPref = 
getActivity() . getPreferences(Context.MODE_PRIVATE);

Pentru a partaja un fișier de preferințe, acesta trebuie creat cu modul MODE_WORLD_READABLE sau MODE_WORLD_WRITABLE. În acel moment, orice aplicație care cunoaște numele fișierului de preferințe poate să îl acceseze. Din aceste motive, este indicat ca numele să fie cât mai clar legat de aplicație prin folosirea unei denumiri asemănătoare cu package-urile. De exemplu: com.example.myapp.PREFERENCES.

Este bine de știut că SharedPreferences nu se referă explicit la salvarea preferințelor utilizatorilor, cum ar fi, de exemplu, nivelul soneriei. Pentru a oferi această facilitate, trebuie implementată în aplicație PreferenceActivity care oferă o activitate pentru aceasta și care va persista valorile automat, folosind API-ul de SharedPreferences.

Scrierea

Pentru a putea scrie valori în cadrul SharedPreferences, trebuie folosit un editor. Deoarece aceste valori pot fi foarte sensibile pentru aplicație, modul de scriere seamănă un pic cu tranzacțiile. Astfel, valorile nu sunt memorate decât în momentul în care editorul este anunțat să facă commit pe setul de modificări care a avut loc de la ultima schimbare. Practic, editorul este o clasă internă a SharedPreferences și o instanță a sa poate fi obținută ușor:

SharedPreferences.Editor editor = sharedPref.edit();

Avem o metodă dedicată pentru fiecare tip primitiv, pentru a reține valori. În general, metodele put* primesc numele cheii și valoarea. Dacă cheia există deja, ea va fi modificată, dacă nu, o cheie nouă va fi creată. Și aici este bine să păstrăm aceeași convenție de denumire, amintită mai sus.

Modificările nu vor fi scrise în fișier decât în momentul în care este apelat commit sau apply.

editor.putInt(”com.example.preference.keys.INTEGER_VALUE”, 100);
editor.putString((”com.example.preference.keys.BOOL_VALUE”, true);
editor.putBoolean((”com.example.preference.keys.STRING_VALUE”, ”string”);
editor.commit();

Citirea

Pentru a citi o valoare, nu mai avem nevoie de editor, putem folosi direct obiectul de SharedPreferences. Citirea se face tot prin intermediul unor metode dedicate pentru fiecare tip primitiv.

int int_value = 
sharedPref.getInt(”com.example.preference.keys.INTEGER_VALUE”, 
defaultValue);

Valoarea variabilei defaultValue este returnată în cazul în care nu se găsește o valoare salvată pentru cheia respectivă.

Tips

După cum se poate observa, mecanismul este foarte simplu, dar nu simplist. Iată și câteva sfaturi utile pentru a-l putea folosi cât mai eficient:

1. Folosiți mereu nume unice pentru fișierele și numele de chei asemănătoare cu packet-urile.

com.example.preferences.category.key.KEY_NAME

2. Folosiți fișierul strings.xml pentru a salva numele de fișiere sau de chei și citiți acele nume prin intermediul resurselor.

String keyName = getResources().getString(R.string.key_name);

3. În general, e bine ca preferințele să fie citite în metoda onCreate() și să fie scrie în metoda onStop().

Acest mecanism de persistare a unor informații între instanțele unei aplicații este cel mai simplu și eficient disponibil. Desigur, informațiile mai pot fi persistate în fișiere din spațiul de stocare intern al aplicației sau în spațiul de stocare extern, pe card-ul SD sau în baze de date SQLite, dar despre acestea vom vorbi în articolele viitoare.