ez a cikk az Android Looper, Handler és HandlerThread programokkal foglalkozik. Ezek az Android OS építőkövei közé tartoznak.
saját tapasztalataim szerint a közelmúltig nagyon korlátozott kontextusban használtam őket. A használati esetem során feladatokat küldtem a fő / ui szálra, elsősorban a felhasználói felület bármely más szálból történő frissítésére. A többszálú működés egyéb aspektusait alternatív módon kezelték, mint például a ThreadPoolExecutor, az IntentService és az AsyncTask.
a MultiThreading és a task running Régi témák. Maga a Java rendelkezik java-val.util.egyidejű csomag és Fork / Join keretrendszer annak megkönnyítése érdekében. Számos könyvtárat írtak az aszinkron műveletek egyszerűsítésére. RxJava a legnépszerűbb könyvtár ma reaktív programozás és tervezése egy aszinkron alkalmazás.
szóval, miért írok a régi iskoláról?
Looper
, Handler
, a HandlerThread
pedig az Android módja az aszinkron programozás problémáinak megoldására. Nem régi iskola, hanem egy ügyes struktúra, amelyre egy összetett android keret épül.
az új fejlesztők számára erősen ajánlott megérteni a mögöttük álló elveket, és a tapasztalt embereknek újra meg kell vizsgálniuk ezt a témát, hogy emlékezzenek a kisebb részletekre.
én is létrehozott egy videót bemutató ebben a témában, és én nagyon ajánlom, hogy nézd meg. Kattintson ide a megtekintéshez.
Használati Esetek:
- az Android fő szála
Looper
ésHandlers
. Tehát a megértése elengedhetetlen egy nem blokkolt reszponzív felhasználói felület létrehozásához. - a könyvtárakat író fejlesztők a könyvtár mérete miatt nem engedhetik meg maguknak, hogy harmadik féltől származó könyvtárakat használjanak. Tehát számukra a legjobb megoldás a meglévő rendelkezésre álló erőforrás felhasználása. A saját megoldás írása nem mindig kapja meg ezt a hatékonyságot és optimalizálást.
- ugyanez az érvelés az SDK-kat szállító vállalatok/magánszemélyek esetében is megfogalmazható. Az ügyfelek változatos implementációkkal rendelkezhetnek, de mindegyikük megosztja a közös android keretrendszer API-kat.
- ezek teljes megértése növeli az Android SDK és a csomagosztályok általános követésének képességét.
kezdjük a feltárást/felülvizsgálatot egy kérdőívvel.
elvárom, hogy az olvasó az alapvető ismereteket a java szálak. Ha szüksége van, akkor kap egy gyors áttekintést java szál és futtatható.
mi a probléma a java szál?
a Java szálak csak egyszer használhatók, és a futtatási módszer végrehajtása után elpusztulnak.
tudunk javítani rajta?
a szál kétélű kard. Felgyorsíthatjuk a végrehajtást azáltal, hogy a feladatokat elosztjuk a végrehajtás szálai között, de lelassíthatjuk azt is, ha a szálak meghaladják. A szál létrehozása önmagában egy felső. Tehát a legjobb megoldás az, ha optimális számú szálat használunk, és újra felhasználjuk őket a feladatok végrehajtásához.
modell a menet újrafelhasználhatóságához:
- a szál életben marad, egy hurokban a
run()
módszerrel. - a feladatot az adott szál sorozatosan hajtja végre, és egy sorban (MessageQueue) tartja fenn.
- a szálat le kell állítani, ha kész.
mi az Android módja ennek?
a fenti modell végre az Android via Looper
, Handler
, és HandlerThread
. A rendszer megjeleníthető, hogy jármű legyen, mint a cikk borítóján.
-
MessageQueue
egy sor, amely feladatokat nevezett üzeneteket kell feldolgozni. -
Handler
enqueues feladat aMessageQueue
segítségévelLooper
és végrehajtja őket, amikor a feladat jön ki aMessageQueue
. -
Looper
egy munkás, amely életben tartja a szálat, hurkol aMessageQueue
– en keresztül, és üzeneteket küld a megfelelőhandler
– nek a feldolgozáshoz. - végül
Thread
megszűnik a Looperquit()
metódusának meghívásával.
egy szálhoz csak egy egyedi hurok tartozhat, és sok egyedi kezelő társítható hozzá.
Looper és MessageQueue létrehozása egy szálhoz:
egy szál Looper
és MessageQueue
számot kap a Looper.prepare()
meghívásával a futtatása után. Looper.prepare()
azonosítja a hívó szálat, létrehoz egy Looper
és MessageQueue
objektumot, és társítja a thread
– et velük a ThreadLocal
tárolási osztályban. Looper.loop()
meg kell hívni, hogy indítsa el a kapcsolódó looper. Hasonlóképpen, a looper
– et kifejezetten a looper.quit()
– on keresztül kell befejezni.
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here // this will run in non-ui/background thread } }; Looper.loop(); } }
kezelő létrehozása egy szálhoz:
a Handler
implicit módon kapcsolódik ahhoz a szálhoz, amely a szál Looper
– en keresztül példányosítja, de kifejezetten egy szálhoz köthetjük, ha átadjuk a szál looper
– ét a Handler
konstruktorában.
handler = new Handler() {@Overridepublic void handleMessage(Message msg) { // process incoming messages here // this will run in the thread, which instantiates it }};
üzenetek küldése a MessageQueue
keresztül Handler
lehet tenni két mód:
-
Message
: ez egy osztály, amely különféle hasznos módszereket határoz meg az üzenetadatok kezelésére. Egy objektum elküldéséhez az obj változót állítjuk be.
Message msg = new Message();msg.obj = "Ali send message";handler.sendMessage(msg);
a Message
osztály részletes áttekintése itt található: https://developer.android.com/reference/android/os/Message.html
Runnable
: a futtatható is írt a MessageQueue
. Például: feladat feladása és futtatása a fő szálban.
new Handler(Looper.getMainLooper()).post(new Runnable() {@Overridepublic void run() { // this will run in the main thread }});
a fenti példában létrehozunk egy Handler
– et, és megadjuk a fő szálhoz társított Looper
– et. Ez társítja ezt a kezelőt a fő szálhoz. Amikor elküldjük a Runnable
– et, a fő szál MessageQueue
– jében sorba kerül, majd végrehajtja a fő szálban.
a kezelő sokféle módon képes az üzenetek manipulálására, ami itt található: https://developer.android.com/reference/android/os/Handler.html
saját szál létrehozása és a Lopper
és a MessageQueue
megadása nem a megfelelő módszer a probléma kezelésére. Tehát az Android a HandlerThread
(Thread
alosztálya) biztosítja a folyamat egyszerűsítését. Belsőleg ugyanazokat a dolgokat teszi, mint mi, de robusztus módon. Tehát mindig használja a HandlerThread
értéket.
a HandlerThread létrehozásának egyik módja az alosztályozás, és legtöbbször ezt a módszert fogja használni.
private class MyHandlerThread extends HandlerThread { Handler handler; public MyHandlerThread(String name) { super(name); } @Override protected void onLooperPrepared() { handler = new Handler(getLooper()) { @Override public void handleMessage(Message msg) { // process incoming messages here // this will run in non-ui/background thread } }; }}
megjegyzés: a kezelőt a onLooperPrepared()
meghívásakor példányosítottuk. Tehát, hogy Handler
lehet társítani, hogy Looper
.
-
Looper
csak a HandlerThreadstart()
meghívása után készül, azaz a szál futása után. - a
Handler
társítható aHandlerThread
– hoz, csak aLooper
elkészítése után.
a HandlerThread létrehozásának másik módja:
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");handlerThread.start();Handler handler = new Handler(handlerThread.getLooper());
Megjegyzés: HandlerThread kell hívni myHandlerThread.quit()
, hogy felszabadítsa a forrásokat, és állítsa le a végrehajtását a szál.
azt javaslom, hogy gyakorolja a fenti kódokat, így megértheti az apró részleteket.
létrehoztam egy Példaprojektet a Posta szimulációjához. Posta épül HandlerThread és az ügyfelek kommunikálni segítségével a Posta. A szimulátor osztály létrehoz néhány kliens botok és delegálni a kommunikációt a MainActivity, amely teszi, hogy egy élő takarmány.
a link erre a példára
én is létrehozott egy videót bemutató ebben a témában, és én nagyon ajánlom, hogy nézd meg. Kattintson ide a megtekintéshez.
legyünk barátok a Twitteren, a Linkedin-en, a Githubon és a Facebook-on is.
a tanulás egy utazás, tanuljunk együtt!