Az Android alkalmazások fejlesztése során a Fragmentek alapvető fontosságúak a képernyőn megjelenő felületek hatékony kezelésében. Az egyik gyakran alkalmazott minta a Master/Detail minta, amely különösen hasznos a listák megjelenítésére és a részletező információk bemutatására, különösen, ha az alkalmazás több képernyőorientációt is támogat, mint például a portré és a tájolás módok. Az alábbiakban bemutatom, hogyan érhetjük el a Fragmentek közötti hatékony kommunikációt Android alkalmazásban, egy egyszerű példán keresztül.

A Master/Detail minta lényege, hogy két Fragmentet használunk: az egyik a lista megjelenítésére szolgál (Master Fragment), míg a másik a választott elem részleteit mutatja be (Detail Fragment). Ezenkívül, ha az alkalmazás tájolás módot is figyelembe vesz, akkor szükséges, hogy az eszköz képes legyen mindkét Fragment egyidejű megjelenítésére vagy az egyik helyett a másik mutatására, attól függően, hogy az alkalmazás éppen portré vagy tájolás módban fut.

Első lépésként egy új projektet kell létrehoznunk az Android Studio-ban, amelynek neve „Fragmentcommunication” legyen. Az Activity típusának üres Activity-t válasszunk. Az alkalmazás képes lesz a Fragmentek közötti kommunikációra, miután létrehoztuk azokat. A Master Fragment a ListFragment osztályt fogja örökölni, így nem szükséges saját elrendezést készíteni. A tájolás módokhoz kapcsolódóan két különböző elrendezést fogunk készíteni: egyet a portré módhoz és egyet a tájolás módhoz. A portré módban az egyik Fragmentet a másik helyére cseréljük, míg tájolás módban mindkét Fragmentet egyszerre jelenítjük meg.

A következő lépésben egy új Java osztályt kell létrehoznunk MasterFragment néven, amely a ListFragment osztályból származik. Ezen Fragmenten belül definiálunk egy interfészt OnMasterSelectedListener néven, amely lehetővé teszi, hogy az alkalmazás a listából kiválasztott elem nevét továbbítsa a Detail Fragmentbe. Az interfészt a setOnMasterSelectedListener() metódus segítségével aktiváljuk. A lista adapter segítségével a listát feltöltjük, és egy kattintás eseményre egy callback-t indítunk, amely a választott ország nevét továbbítja a Detail Fragmentbe.

Ezután létrehozzuk a Detail Fragmentet, amely tartalmazza a részletes információkat az egyes országokkal kapcsolatban. Az adatokat a Fragment argumentumoként adjuk át, így a Bundle segítségével tudjuk kezelni őket. A kiválasztott ország nevét a showSelectedCountry() metódussal jelenítjük meg a TextView-ban.

Az Activity elrendezését is módosítani kell, hogy támogassa mind a portré, mind a tájolás módot. Az Activity alapértelmezett elrendezését a activity_main.xml fájlban határozzuk meg. A tájolás módhoz külön mappát hozunk létre a res/layout-land könyvtárban, ahol a tájolás módhoz illeszkedő elrendezést helyezünk el.

A végső lépésben a MainActivity-ben kell beállítanunk a Fragments kezelését. Az Activity a Fragmentek között váltogat, és figyelembe veszi a tájolás módot. Ha a képernyő nem elég széles a két Fragment egyidejű megjelenítéséhez, akkor a Master Fragment betöltődik, és a Detail Fragment külön jelenik meg, amikor egy listaelemre kattintunk.

Fontos, hogy a Fragmentek közötti kommunikáció és a képernyőorientációk kezelése a felhasználói élmény szempontjából kulcsfontosságú. A tájolás módok és a Fragmentek dinamikus kezelésének megértése nélkülözhetetlen az alkalmazások fejlesztésekor, mivel a felhasználói élmény folyamatosan változik a képernyő méretének és az eszköz orientációjának megfelelően. A Fragmentek közötti adatátvitel pedig nemcsak a képernyőn megjelenő elemek kezelésére, hanem az alkalmazás áramlásának és funkcionális felépítésének javítására is alapvetően hatással van.

Hogyan hozhatunk létre, frissíthetünk és törölhetünk rekordokat egy SQLite szótáralkalmazásban Androidon?

Az Android SQLite adatbázis-kezelése során gyakran felmerül az igény, hogy egyedi alkalmazásainkhoz helyben tároljunk strukturált adatokat. A szótáralkalmazás esete jó példa arra, hogyan lehet ezt elegánsan megvalósítani egy egyedi SQLiteOpenHelper-osztály segítségével. A DictionaryDatabase osztály a teljes adatkezelési logikát egy helyen koncentrálja.

Az osztály konstruktorában a super() hívás inicializálja az adatbázist, figyelembe véve a név, verziószám és egyéb paramétereket. A DATABASE_VERSION kulcsfontosságú: ennek módosítása váltja ki az onUpgrade() metódus hívását, amelyet akkor kell implementálni, ha az adatbázis sémája változik. Az onCreate() csak az első futtatáskor hívódik meg, létrehozva a dictionary nevű táblát, amely három mezőt tartalmaz: _id, word és definition. Fontos megjegyezni, hogy az _id mezőnek elsődleges kulcsnak kell lennie, mivel az Android CursorAdapter-ei ezt megkövetelik.

A rekordok hozzáadását, frissítését és törlését külön metódusok végzik. A saveRecord() intelligens módon eldönti, hogy új rekordot kell-e hozzáadni, vagy egy meglévőt frissíteni. Ez a döntés a findWordID() metódus által visszaadott azonosító alapján történik, amely egy SQL-lekérdezés révén próbálja megtalálni az adott szóhoz tartozó rekordot. A getWritableDatabase() segítségével írásra képes példányt szerzünk az adatbázisból, míg a ContentValues osztály kulcs-érték párokban rendezi az adatokat, amelyek beszúrhatók vagy frissíthetők.

A deleteRecord() metódus hasonló logikát követ, ahol a rekord azonosítója alapján történik a törlés. Ez egy lényegre törő, szinkron eljárás, amely azonnali visszajelzést nyújt a törölt rekordok számáról.

Az adatok lekérdezésére szolgáló metódusok, mint a getDefinition(), getWordList() és findWordID() az SQLiteDatabase olvasható változatát használják. Ezek az eljárások Cursor objektummal térnek vissza, amely lehetővé teszi a táblázat sorainak bejárását. A getWordList() különösen fontos, mert ez biztosítja az alkalmazás felhasználó

Hogyan lehet visszaadni egy eredményt egy másik Activity-ből Android alkalmazásban?

A startActivityForResult() metódus egy egyszerű megoldást kínál arra, hogy adatokat küldjünk és eredményt kapjunk vissza egy Activity hívása során. Az Activity-k közötti kommunikáció, amikor az egyik Activity-ből adatokat kell visszaadni egy másiknak, alapvetően hasonló a korábbi példákban látottakhoz, azonban egy kis extra lépést igényel.

A folyamat elkezdéséhez először is hozz létre egy Android projektet két Activity-vel, és gondoskodj arról, hogy legyen egy mód az Activity-k közötti kommunikációra. Az alábbi lépések segítségével biztosítható, hogy a második Activity vissza tudja adni a szükséges eredményeket.

Első lépésként nyisd meg a MainActivity.java fájlt, és adj hozzá egy konstans változót a class szintjén, hogy könnyedén hivatkozhass a kért eredmény kulcsára:

java
public static final String REQUEST_RESULT="REQUEST_RESULT";

Ezután módosítsd az onClickSwitchActivity() metódust, hogy az várjon egy eredményt a másik Activity-ből. Az Intent létrehozásakor már beállítható, hogy eredményt várunk:

java
public void onClickSwitchActivity(View view) { EditText editText = (EditText)findViewById(R.id.editTextData); String text = editText.getText().toString();
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra(Intent.EXTRA_TEXT, text); startActivityForResult(intent,
1); }

Ezután implementáld az onActivityResult() metódust, hogy a rendszer visszaküldhesse az adatokat, ha azokat a második Activity sikeresen visszaadta:

java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { Toast.makeText(this, Integer.toString(data.getIntExtra(REQUEST_RESULT, 0)), Toast.LENGTH_LONG).show(); } }

Most pedig a második Activity-ben szükséges módosításokat elvégezni. Az onClickClose() metódust úgy kell módosítani, hogy visszaadja a szükséges eredményt:

java
public void onClickClose(View view) {
Intent returnIntent = new Intent();
returnIntent.putExtra(MainActivity.REQUEST_RESULT,
42); setResult(RESULT_OK, returnIntent); finish(); }

Hogyan működik?

A visszaadás folyamata viszonylag egyszerű. A startActivityForResult() metódust hívjuk meg, amely jelzi, hogy egy eredményre van szükség. Ezután az onActivityResult() metódust használjuk, hogy az adatokat visszakapjuk a hívó Activity-be. Végül, a második Activity-ben a setResult() metódus biztosítja, hogy az eredmény visszakerüljön a hívó Activity-hez.

Fontos, hogy mindig ellenőrizzük az eredmény kódját, hogy biztosak legyünk benne, hogy a felhasználó nem mondta le az akciót. Bár az eredmény kódja technikailag egy egész szám, a rendszer boolean értékként használja azt. Az RESULT_OK vagy RESULT_CANCEL értékekre kell figyelni, és ennek megfelelően kell eljárni. Ha például a felhasználó a vissza gombot nyomja, akkor az eredmény kódja RESULT_CANCEL lesz, és az Intent null értéket kaphat, ami kivételt eredményezhet.

A Toast objektum használata hasznos eszköz arra, hogy a felhasználót értesítsük anélkül, hogy külön UI elemet kellene hozzáadnunk. Ezen kívül a Toast kiváló eszköz a hibakereséshez is, mivel nem igényel külön elrendezést vagy képernyő helyet.

További információk

A onActivityResult() metódus nem csupán az eredmény kódját, hanem a kérés kódját is tartalmazza. A kérés kódja az a szám, amelyet a startActivityForResult() metódus hívásakor adunk meg. Az alábbi módon adjuk meg a kódot:

java
startActivityForResult(Intent intent, int requestCode);

A példában csak egyetlen eredmény kódot kezelünk, ezért nem szükséges ellenőrizni a kérés kódját. Azonban ha több Activity-vel rendelkező alkalmazásunk van, a kérés kódja segíthet meghatározni, hogy honnan származik az eredmény. Ha a kérés kódja negatív, az olyan, mintha a startActivity() metódust használnánk, így nem várunk eredményt vissza.

Az Activity-k állapotának mentése

A mobilkörnyezet dinamikus és változékony, a felhasználók gyakran váltanak feladatokat, ami miatt elvárható, hogy az alkalmazásunkat bárhol megszakíthassa a rendszer, hogy helyet adjon más folyamatoknak. Gyakran a rendszer teljesen leállítja az alkalmazásokat, hogy erőforrást szabadítson fel.

Ezeket a megszakításokat figyelembe kell venni, és megfelelően kell kezelni az alkalmazás állapotát, hogy a felhasználó mindig könnyen folytathassa onnan, ahol abbahagyta. Az Android operációs rendszer biztosítja az állapotváltozások kezelésére szolgáló visszahívásokat, például a onSaveInstanceState() és onRestoreInstanceState() metódusokat, amelyek segítenek az alkalmazásunk állapotának mentésében és visszaállításában.

Ha egy felhasználó elhagyja az alkalmazást, majd visszatér, a rendszer automatikusan újraépíti az Activity-t. Ha a felhasználó megváltoztatja az eszköz orientációját, a rendszer újraindítja az Activity-t. Ezt célszerű figyelembe venni, hogy az alkalmazásunk a helyes elrendezést és erőforrást használja.

A onSaveInstanceState() metódus használatával elmenthetjük a fontos adatokat, mint például egy számlálót, amit minden egyes gombnyomáskor növelhetünk, majd a onRestoreInstanceState() segítségével visszaállíthatjuk az állapotot, ha az alkalmazás újraindul.

java
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); outState.putInt(KEY_COUNTER, mCounter); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mCounter = savedInstanceState.getInt(KEY_COUNTER); }

Ez biztosítja, hogy az alkalmazásunk a felhasználó által végzett interakciókat megőrizze, és képes legyen visszaállni az eredeti állapotba, amikor a rendszer újraindítja azt.