A layoutok kezelése az Android fejlesztésében elengedhetetlen része az alkalmazások hatékonyságának biztosításának. Az Android rendszerben minden egyes elemnek (View) és ezek csoportjának (ViewGroup) saját elrendezési paraméterei vannak, amelyek meghatározzák azok kívánt magasságát, szélességét és elhelyezkedését. Az elrendezések kezelése alapvető fontosságú, mivel az alkalmazás sebessége és a felhasználói élmény nagymértékben függ a helyes megvalósítástól. Az alábbiakban bemutatjuk, hogyan használhatjuk a Hierarchy Viewert és más eszközöket a layoutok optimalizálására.
Először nézzük meg, hogyan állíthatunk be eseménykezelőt egy gombhoz, amely lehetővé teszi számunkra, hogy dinamikusan módosítsuk az elrendezést. Ehhez szükség van az onClick események kezelésére. Az alábbi kód egy egyszerű példát mutat be, amely egy gomb megnyomásakor változtatja meg a szöveget és módosítja annak elhelyezkedését:
Ez a kód például arra szolgál, hogy egy gomb megnyomásakor változtassa meg a szöveget, valamint módosítja annak bal oldali margóját. A View elemekhez rendelt LayoutParams segítségével hozzáférhetünk a nézetek elrendezési paramétereihez, és szükség esetén módosíthatjuk azokat. Az elrendezési paraméterek az egyes elemek szélességét, magasságát, margóit és más, a nézetekhez tartozó beállításokat tartalmaznak.
A layoutok optimalizálása előtt fontos megérteni az Android elrendezési folyamatát. Amikor egy aktivitás betöltődik, három fő lépés zajlik le:
-
Mérés: Ebben a szakaszban a nézetek meghatározzák a méretüket, először a szülő nézet, majd az összes gyermeknézet is. Előfordulhat, hogy a szülő többször is kérni fogja a gyermekeket, hogy pontosan meghatározza azok méretét.
-
Elrendezés: Ekkor a szülő meghatározza a gyermekek pozícióját.
-
Rajzolás: Végül a nézetek renderelésre kerülnek.
Ezek a lépések egy hierarchikus struktúrában zajlanak, ahol a szülő nézet a fa gyökere, és minden egyes gyermek nézet az ő alárendeltje.
A Hierarchy Viewer egy olyan eszköz, amely segít megérteni és optimalizálni a layoutok működését. Az eszköz lehetővé teszi, hogy vizuálisan megjelenítsük a layout fa struktúráját és annak időbeli alakulását. Így könnyen felismerhetők az olyan problémák, mint a túlzottan bonyolult elrendezések, amelyek felesleges iterációkat eredményezhetnek a mérési lépés során. Az eszköz használatával gyorsan felfedezhetjük a bottleneckeket, és ennek megfelelően javíthatjuk a felhasználói élményt.
A Hierarchy Viewer használatának lépései a következőképpen alakulnak:
-
Nyissuk meg az "OptimizingLayouts" nevű projektet Android Studio-ban, és futtassuk azt egy rooted eszközön vagy emulatoron.
-
Az Android Studio-ban indítsuk el az Android Device Monitor-t, majd váltsunk a Hierarchy View nézetre.
-
A bal oldali ablakban válasszuk ki az éppen futó alkalmazást, és nézzük meg a layout grafikus megjelenítését a középső panelen.
Ez a vizuális reprezentáció segít abban, hogy gyorsan észrevegyük azokat a helyeket, ahol a layoutok nem optimálisak. Például, ha mélyen beágyazott LinearLayout-ok vannak, azok feleslegesen növelhetik az alkalmazás betöltési idejét és a felhasználói interakciók válaszidejét.
A layout optimalizálása során a RelativeLayout használata sok esetben jobb megoldás lehet, mint a mélyen egymásba ágyazott elrendezések. A RelativeLayout laposabb struktúrát biztosít, amely csökkenti a szükséges iterációk számát a méretezési lépés során. Így még akkor is, ha a layout nem tűnik rendkívül bonyolultnak, a felhasználói élmény javítása érdekében érdemes az optimalizálásra összpontosítani.
A Lint egy másik hasznos eszköz, amely automatikusan figyelmeztethet bennünket a layoutokkal kapcsolatos problémákra. Például, ha túl mélyre ágyazott nézeteket vagy felesleges szülőket használunk, a Lint figyelmeztetést ad. Ezen kívül figyelmeztethet a nem szükséges levél elemekre is, amelyek nem végeznek hasznos munkát a layoutban.
Egy másik optimalizálási módszer a ViewStub használata, amely lehetővé teszi, hogy csak akkor töltsünk be egy layoutot, amikor valóban szükség van rá. A ViewStub használatával jelentősen csökkenthetjük az alkalmazás memóriahasználatát és gyorsíthatjuk annak betöltését. Például, ha van egy ritkán használt funkció, mint egy nyomtatási lehetőség, akkor azt a ViewStub segítségével késleltetve tölthetjük be, amikor a felhasználó igényli.
A fenti technikák alkalmazásával érdemes tisztában lenni azzal, hogy minden elrendezésnél figyelembe kell venni a felhasználói élményt. Az alkalmazás hatékonysága nem csupán a gyorsaságot, hanem a memóriahasználatot is befolyásolja. Ha túl sok nézetet töltünk be egyszerre, az hosszú távon csökkentheti az alkalmazás teljesítményét. Ezért a layoutok optimalizálása nemcsak a megjelenítés gyorsítását jelenti, hanem a rendszer erőforrásainak hatékony kezelését is.
Hogyan lehet egyéni nézeteket és erőforrásokat létrehozni Android alkalmazásokban?
Az Android fejlesztés során gyakran találkozunk azzal a helyzettel, hogy nem elegendő a rendszer által biztosított vizuális komponensek és erőforrások használata. Ilyenkor a testreszabás és a teljes vezérlés igénye megköveteli, hogy egyedi grafikai elemeket vagy akár teljesen saját nézeteket hozzunk létre. Ennek egyik kulcsa a drawable erőforrások és az egyedi View osztályok használata.
Az @drawable hivatkozás azt jelzi az Android rendszernek, hogy egy vizuális elemet (például háttérképet, állapotfüggő gombgrafikát stb.) kell betölteni a res/drawable mappából. Amennyiben különböző képfelbontásokat szeretnénk támogatni, célszerű azokat a megfelelő density-specifikus mappákba helyezni: drawable-ldpi, drawable-mdpi, drawable-hdpi, drawable-xhdpi. Ezek biztosítják, hogy az adott eszköz a legmegfelelőbb minőségű képet töltse be. Ha az adott mappa üres, a rendszer automatikusan a következő legjobb illeszkedésűt keresi.
A felhasználói felület dinamikus manipulálása szintén fontos technika. Bár az elrendezéseket általában XML-ben definiáljuk, előfordulhat, hogy futásidőben kell egy új elemet hozzáadnunk. Például a DatePicker komponens hozzáadása egy már meglévő RelativeLayout-hoz Java kódból viszonylag egyszerű: először referenciát szerzünk a layout-hoz a findViewById() segítségével, majd addView() metódussal hozzáadjuk az új elemet. Ez a megközelítés lehetőséget nyújt a rugalmas, feltételekhez kötött felületek kialakítására.
Sőt, akár az egész elrendezés is létrehozható kódból. Ilyenkor nem használjuk az XML fájlokat, hanem a setContentView() metódusban közvetlenül egy újonnan példányosított layout-ot állítunk be. Ez persze kevésbé átlátható nagyobb felületeknél, de bizonyos esetekben – például kis prototípusoknál vagy egyszerű dinamikus felületeknél – mégis hatékony megoldás lehet.
A következő lépés a teljesen egyedi komponensek létrehozása. Ez akkor válik szükségessé, amikor az előre definiált widgetek nem felelnek meg a kívánt funkcionalitásnak vagy megjelenésnek. Egy egyedi View osztály létrehozása során az első lépés a View osztályból való származtatás. A konstruktorban beállíthatjuk azokat az attribútumokat, amelyek a megjelenéshez szükségesek, például egy Paint objektum színét és szövegméretét.
Az onDraw() metódus felülírásával teljes kontrollt kapunk a komponens rajzolása felett. A rendszer a Canvas objektumot biztosítja, amelyre saját rajzainkat, szövegeinket, vonalainkat vagy bármilyen grafikai elemet felvihetünk. Ez lehetővé teszi például animált grafikák, játékobjektumok vagy komplex vizuális komponensek létrehozását.
Fontos, hogy ha a teljes felületet egy ilyen komponensből kívánjuk megjeleníteni, akkor a setContentView() meghívásakor közvetlenül ezt az egyedi nézetet adjuk meg. Mivel az onMeasure() metódus nincs felülírva, a rendszer alapértelmezés szerint 100x100-as méretet rendel a komponenshez, kivéve, ha a teljes képernyőt lefedi, ilyenkor az elérhető helyet automatikusan kitölti.
Ha az egyedi nézetet később újra el kell érnünk, célszerű ID-t rendelni hozzá. Ezt vagy XML-ben definiálhatjuk, vagy a setId(View.generateViewId()) metódussal futásidőben hozzárendelhetjük. Így biztosíthatjuk, hogy a nézet a későbbiekben is programozottan elérhető maradjon.
A fejlesztés során a rugalmasság és az újrahasználhatóság szempontjából különösen fontos a komponensek modularizálása. Az egyedi nézetek külön Java osztályba helyezése nemcsak a karbantarthatóságot növeli, hanem lehetővé teszi azok újbóli felhasználását más projektekben is.
A fejlesztő számára lényeges megérteni az Android erőforráskezelésének logikáját és azt, hogyan reagál a rendszer különböző kijelzőspecifikus mappák tartalmára. Továbbá a nézetek dinamikus kezelése és az egyedi komponensek létrehozása azok az eszközök, amelyekkel a felhasználói élmény testre szabható és adaptálható a különböző eszközökön.
A rajzolás optimalizálása, az invalidate() metódus megfelelő használata, valamint a mértékek és méretezések kezelése az onMeasure() felülírásával elengedhetetlen, ha interaktív vagy erőforrás-igényes felületeket kívánunk készíteni.
Miért érdemes a Volley könyvtárat használni HttpURLConnection helyett Android-fejlesztés során?
Az Android hosszú éveken át több lehetőséget kínált az internetes lekérdezések lebonyolítására. Kezdetben az Apache HttpClient volt az ajánlott megoldás, különösen a Gingerbread (API 9) verzió előtt. Azonban a 2.3-as verzióval jelentős fejlesztések történtek a HttpURLConnection könyvtárban, amely ezzel átvette a hivatalosan támogatott szerepet, és a mai napig az Android SDK alapértelmezett eszköze. Az Android 6.0 kiadásával az Apache HttpClient végleg kikerült az SDK-ból, így minden új fejlesztésnek HttpURLConnection-re kellett épülnie.
Mindezek ellenére a HttpURLConnection nem kínál elegendő rugalmasságot és túl sok ismétlődő, sablonos kódot igényel. Ez különösen kezdők számára nehezíti meg az internetes kapcsolatok kezelését. Itt lép be a képbe a Volley, amelyet Ficus Kirkpatrick, a Google Play fejlesztőcsapatának tagja hozott létre. A Volley a HttpURLConnection-re épül, de egy magasabb szintű absztrakciót nyújt, csökkentve a kódsorok számát, egyszerűsítve a szálkezelést és átláthatóvá téve a gyorsítótárazást.
A Volley több jelentős előnnyel rendelkezik: saját szálkezelő rendszert használ (alapértelmezésben négy szálon), automatikusan kezeli a lemezalapú gyorsítótárat, és lehetőséget biztosít a lekérdezések prioritásának meghatározására. Ezek az előnyök különösen fontosak, ha több, kis méretű kérést szeretnénk párhuzamosan kezelni, például egy ListView görgetése közben.
A Volley legnagyobb ereje az egyszerűségében rejlik. A fejlesztőnek nem kell minden lekérdezés köré try/catch blokkokat írnia – a hibakezelés beépített, és csak a konkrét működésre kell koncentrálni. Támogatja a String, JSON, Image és egyedi lekérdezések típusait is. Fontos azonban megjegyezni, hogy a Volley nem ideális nagy fájlok letöltésére, mert minden választ memóriában dolgoz fel, ami nagy erőforrás-igénnyel jár. Ilyen esetekben a DownloadManager használata ajánlott. Ugyanez érvényes a streamelt tartalmakra is: ezeket továbbra is HttpURLConnection segítségével célszerű kezelni.
A Volley nem része az Android SDK-nak, ezért manuálisan kell letölteni a forráskódját a Google hivatalos AOSP repository-jából, majd modulként importálni az Android Studio projektbe. Ez

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