Az Android platform sajátos életciklusa és erőforráskezelése miatt az aktivitások állapotának mentése és visszaállítása nemcsak ajánlott, hanem gyakran elengedhetetlen. Az onSaveInstanceState() és az onRestoreInstanceState() visszahívási metódusok segítségével lehetőségünk van ideiglenesen megőrizni adatokat, például egy számláló értékét vagy más primitív típusokat, amelyek a képernyő elfordításakor vagy memóriahiány miatt végbemenő folyamatleállításkor elvesznének.
A rendszer egy Bundle objektumot küld ezeknek a metódusoknak, amely név/érték párok segítségével tárolja az adatokat. Fontos tudni, hogy nem minden komponens állapotát menti automatikusan az Android. Az EditText például magától visszaállítja a beírt szöveget, amennyiben rendelkezik egyedi azonosítóval (android:id). Más komponenseknél, mint a TextView, ez nem automatikus, és manuálisan kell elvégezni a mentést.
A visszaállítás nem kizárólag az onRestoreInstanceState() metódusban történhet; az onCreate() is megkapja ugyanazt a savedInstanceState objektumot. Ilyenkor ellenőrizni kell, hogy a kapott objektum nem null, különben felesleges vagy hibás visszaállítási logikát hajtanánk végre:
Ez az átmeneti mentés hasznos, de korlátozott: az adatok csak az aktuális munkamenetre élnek. Ha hosszabb távú tárolásra van szükség – például a felhasználó nevére vagy egy játékeredményre –, akkor a SharedPreferences használata válik szükségessé. Ez egy könnyűsúlyú, név/érték párokat tároló mechanizmus, amely a háttérben fájlba írja az adatokat, és újraindítás után is visszatölthetők.
A SharedPreferences mentéséhez az onPause() metódusban hívjuk meg a következő kódot:
A visszatöltés az onCreate() végén történhet:
A SharedPreferences lehetőséget ad több fájl kezelésére is a getSharedPreferences(String name, int mode) metódussal, így külön konfigurációs egységeket hozhatunk létre, ami skálázhatóbbá teszi az alkalmazást. A MODE_PRIVATE használata biztosítja, hogy az adatokhoz kizárólag az alkalmazás férjen hozzá.
Az Android aktivitások életciklusának megértése kritikus, hiszen a rendszer bármikor leállíthatja az aktivitásokat. Egy aktivitás különböző állapotokon megy keresztül: onCreate(), onStart(), onResume(), majd egy másik aktivitás megjelenésekor onPause(), onStop() és végül onDestroy(). A rendszer akár figyelmeztetés nélkül is megszüntetheti az aktivitást memóriahiány esetén, ezért a kulcsfontosságú adatok mentése nem lehet opcionális.
Mindezen mechanizmusok megértése és helyes használata nem csupán a hibák elkerüléséhez járul hozzá, hanem ahhoz is, hogy az alkalmazás professzionális, stabil és felhasználóbarát élményt nyújtson.
Fontos, hogy a fejlesztő pontosan megértse, mikor és milyen körülmények között hívódnak meg az életciklus-metódusok, és ezeket tudatosan használja. Az onPause() ideális hely az ideiglenes mentésre, az onCreate() és onRestoreInstanceState() pedig a visszaállításra. Kerülendő, hogy a mentést kizárólag az onDestroy()-ra bízzuk, mert az nem mindig hívódik meg – például amikor a rendszer az alkalmazást azonnal bezárja
Hogyan állítsunk be és kezeljünk riasztásokat Androidban az AlarmManager segítségével?
Az Android rendszer működéséből adódóan, amikor egy eszköz újraindul, minden korábban beállított riasztás elveszik. Ezért az alkalmazás felelőssége, hogy újraregisztrálja azokat az eszköz indulásakor. A riasztások hatékony kezeléséhez az AlarmManager osztály nyújt API-t, melynek helyes használata elengedhetetlen, különösen akkor, ha az alkalmazásunknak hosszú távon is stabilan kell működnie.
A riasztás beállítása egy PendingIntent létrehozásával kezdődik, amely egy BroadcastReceiver-t céloz meg. Ezt a BroadcastReceiver osztályt implementálni kell, és fel kell készíteni arra, hogy adott művelet (Action) beérkezésekor végrehajtsa a kívánt logikát. A riasztásokat leggyakrabban gombnyomásra indítjuk, amelyhez egy egyszerű UI komponens – például egy gomb – is elegendő.
Az AlarmBroadcastReceiver osztályban az onReceive() metódus felelős az Intent-ek fogadásáért. Ott kell ellenőrizni, hogy a beérkező művelet megegyezik-e az általunk definiált konstanssal (például: "com.packtpub.androidcookbook.alarms.ACTION_ALARM"), és csak ebben az esetben szabad a műveletet feldolgozni. Ez a fajta ellenőrzés elengedhetetlen, ha egyetlen BroadcastReceiver több műveletet is kezel.
Az AlarmManager.set() metódus használatakor meg kell adnunk az időzítés típusát (AlarmType), a riasztás időpontját, valamint a PendingIntent példányát. A SystemClock.elapsedRealtime() segítségével relatív időt is megadhatunk, például 30 perc múlva aktiválódó riasztást.
Android 4.4 (API 19) óta a rendszer az AlarmManager.set() hívást nem garantáltan pontos időben hajtja végre, hanem a hatékonyság érdekében egy hozzávetőleges időintervallumba sorolja. Ha pontos időzítésre van szükség, a setExact() metódus alkalmazása ajánlott.
Fontos megérteni, hogy a rendszer egyazon PendingIntent alapján csak egy riasztást tud kezelni. Ha ugyanazzal a PendingIntent-tel újra beállítunk egy riasztást, az előzőt automatikusan felülírja. Többszörös riasztás kezeléséhez különböző PendingIntent példányokat kell létrehozni, például eltérő Action stringekkel vagy különböző requestCode értékekkel.
Ha riasztást szeretnénk törölni, a cancel() metódust kell használni, ugyanazzal a PendingIntent-tel, amellyel a riasztást létrehoztuk. Ismétlődő riasztásokhoz a setRepeating() metódus érhető el, amely lehetővé teszi intervallum megadását. Ilyen intervallum lehet például 15 perc (INTERVAL_FIFTEEN_MINUTES), 30 perc, 1 óra vagy egy nap.
Azonban a riasztások újraindítás utáni megőrzéséhez szükséges, hogy az alkalmazás képes legyen észlelni az eszköz újraindítását. Ehhez a RECEIVE_BOOT_COMPLETED engedély szükséges, továbbá a BOOT_COMPLETED műveletre feliratkozott BroadcastReceiver. Ekkor az Android rendszer egy Intent formájában értesíti az alkalmazást az újraindításról, amely lehetőséget ad arra, hogy az elveszett riasztásokat újra létrehozzuk.
A BootBroadcastReceiver osztályon belül az onReceive() metódusban történik a BOOT_COMPLETED esemény azonosítása. Itt kell végrehajtani minden szükséges inicializálást, például korábbi riasztások újbóli beállítását. Fontos megjegyezni, hogy az Android rendszer nem garantálja az indítási események azonnali feldolgozását, így a kódunknak robusztusnak kell lennie, és számolnia kell késleltetésekkel vagy sikertelen indítással.
A BroadcastReceiver struktúra lehetővé teszi, hogy több eseményt is egyetlen osztályon belül kezeljünk. Ehhez elegendő az Intent.getAction() visszatérési értékét vizsgálni és a megfelelő logikát lefuttatni. Így nem szükséges minden eseménytípushoz külön osztályt létrehozni, ezzel csökkentve az alkalmazás komplexitását.
Az Android világában kiemelten fontos, hogy ne terheljük a fő szálat hosszú idejű műveletekkel. Ez különösen igaz a riasztások feldolgozására, mivel a BroadcastReceiver alapértelmezés szerint a fő szálon fut. A hosszabb műveleteket például AsyncTask vagy más háttérszálas konstrukció segítségével érdemes kezelni.
A fejlesztők számára a Google hivatalos dokumentációja – különösen az AlarmManager és az Intent API szekciók – értékes és nélkülözhetetlen információkat tartalmaznak a pontos működésről, viselkedésbeli különbségekről Android verziók között, valamint a lehetséges optimalizációs technikákról.
Az Android rends

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский