dit artikel behandelt Android Looper, Handler en HandlerThread. Deze behoren tot de bouwstenen van Android OS.
in mijn eigen ervaring heb ik ze tot voor kort in een zeer beperkte context gebruikt. Mijn use case betrof het verzenden van taken naar de main / ui thread, voornamelijk om de UI bij te werken vanaf een andere thread. De andere aspecten van de multi-threaded operatie werden behandeld via alternatieve manieren zoals ThreadPoolExecutor, IntentService, en AsyncTask.
MultiThreading en het uitvoeren van taken zijn oude onderwerpen. Java zelf heeft java.util.gelijktijdige pakket en Fork / Join framework om het te vergemakkelijken. Verschillende bibliotheken zijn geschreven om asynchrone operaties te stroomlijnen. RxJava is de meest populaire bibliotheek vandaag voor reactief programmeren en het ontwerpen van een asynchrone toepassing.
dus, waarom schrijf ik over de oude school?
Looper
, Handler
, en HandlerThread
zijn de manier waarop Android de problemen van asynchrone programmering oplost. Ze zijn niet old school, maar een nette structuur waarop een complex android framework is gebouwd.
voor nieuwe ontwikkelaars is het sterk aanbevolen om de principes achter hen te begrijpen en ervaren moet men dit onderwerp opnieuw bekijken om de kleine details te herinneren.
ik heb ook een video tutorial gemaakt voor dit onderwerp, en ik raad ten zeerste aan om het te bekijken. Klik hier om nu te bekijken.
Use Cases:
- de hoofdthread in Android is gebouwd met een
Looper
enHandlers
. Zo, het begrip ervan is essentieel om een niet-geblokkeerde responsieve gebruikersinterface te creëren. - de ontwikkelaars die bibliotheken schrijven kunnen het zich niet veroorloven om bibliotheken van derden te gebruiken vanwege de grootte van de bibliotheek. Dus, voor hen, de beste optie is om de bestaande beschikbare bron te gebruiken. Het schrijven van eigen oplossing voor het kan niet altijd dat niveau van efficiëntie en optimalisatie te krijgen.
- hetzelfde argument kan ook worden aangevoerd voor ondernemingen / particulieren die SDK ‘ s verzenden. De klanten kunnen gevarieerde implementaties hebben, maar ze zullen allemaal de gemeenschappelijke android framework Api ‘ s delen.
- door ze volledig te begrijpen, zal de capaciteit om de Android SDK en pakketklassen in het algemeen te volgen, toenemen.
laten we de verkenning/revisie beginnen met een vragenlijst.
ik verwacht dat de lezer de basiskennis van java threads heeft. Als je nodig hebt, krijg dan een snel overzicht van java Thread en Runnable.
Wat is het probleem met java thread?
Java-threads worden eenmalig gebruikt en verdwijnen na het uitvoeren van de run-methode.
kunnen we dit verbeteren?
de draad is een tweesnijdend zwaard. We kunnen de uitvoering versnellen door de taken over uitvoeringsdraden te verdelen, maar kunnen het ook vertragen wanneer threads overmatig zijn. Draad creatie op zich is een overhead. Dus, de beste optie is om een optimaal aantal threads en hergebruik ze voor de uitvoering van taken.
Model voor herbruikbaarheid van draad:
- de thread wordt levend gehouden, in een lus via de
run()
methode. - de taak wordt serieel uitgevoerd door die thread en wordt onderhouden in een wachtrij (MessageQueue).
- de thread moet worden beëindigd als u klaar bent.
Wat is de manier waarop de Android het doet?
het bovenstaande model is geïmplementeerd in de Android via Looper
, Handler
en HandlerThread
. Het systeem kan worden gevisualiseerd als een voertuig zoals in de dekking van het artikel.
-
MessageQueue
is een wachtrij met taken genaamd berichten die moeten worden verwerkt. -
Handler
onderzoekt taak inMessageQueue
metLooper
en voert deze ook uit wanneer de taak uit deMessageQueue
komt. -
Looper
is een werkerdie een thread levend houdt, doorMessageQueue
loopt en berichten naar de corresponderendehandler
verzendt om te verwerken. - uiteindelijk wordt
Thread
beëindigd door Looper ‘ squit()
methode aan te roepen.
een thread kan slechts één unieke Looper hebben en er kunnen veel unieke Handlers mee geassocieerd zijn.
Looper en MessageQueue aanmaken voor een Thread:
een thread krijgt een Looper
en MessageQueue
door Looper.prepare()
aan te roepen na het draaien. Looper.prepare()
identificeert de aanroepende thread, maakt een object Looper
en MessageQueue
aan en associeert het object thread
met hen in opslagklasse ThreadLocal
. Looper.loop()
moet aangeroepen worden om de geassocieerde looper te starten. Op dezelfde manier moet looper
expliciet worden beëindigd via looper.quit()
.
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(); } }
Handler aanmaken voor een Thread:
A Handler
wordt impliciet geassocieerd met de thread die het instanteert via thread ’s Looper
, maar we kunnen het expliciet aan een thread koppelen door de thread’ s looper
in de constructor van de Handler
door te geven.
handler = new Handler() {@Overridepublic void handleMessage(Message msg) { // process incoming messages here // this will run in the thread, which instantiates it }};
het verzenden van berichten naar de MessageQueue
via Handler
kan op twee manieren gebeuren:
-
Message
: het is een klasse die verschillende nuttige methoden om te gaan met bericht gegevens definieert. Om een object te verzenden stellen we de OBJ variabele in.
Message msg = new Message();msg.obj = "Ali send message";handler.sendMessage(msg);
een gedetailleerd overzicht van de Message
klasse is hier te vinden: https://developer.android.com/reference/android/os/Message.html
Runnable
: een runnable kan ook geplaatst worden in de MessageQueue
. Voorbeeld: een taak posten en uitvoeren in de hoofdthread.
new Handler(Looper.getMainLooper()).post(new Runnable() {@Overridepublic void run() { // this will run in the main thread }});
in het bovenstaande voorbeeld maken we een Handler
aan en geven we Looper
geassocieerd met de hoofdthread. Dit associeert deze handler met de hoofdthread. Wanneer we de Runnable
plaatsen, wordt deze in de wachtrij geplaatst in de hoofd thread MessageQueue
en vervolgens uitgevoerd in de hoofd thread.
Handler is in staat om bericht manipulatie op een breed scala van manieren, die hier kan worden gevonden: https://developer.android.com/reference/android/os/Handler.html
een eigen thread aanmaken en Lopper
en MessageQueue
opgeven is niet de juiste manier om het probleem aan te pakken. Android heeft dus HandlerThread
(subklasse van Thread
) geleverd om het proces te stroomlijnen. Intern doet het dezelfde dingen die wij hebben gedaan, maar op een robuuste manier. Gebruik dus altijd HandlerThread
.
een van de manieren om de HandlerThread aan te maken is door het te subklassen en meestal zult u deze methode gebruiken.
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 } }; }}
opmerking: We hebben de Handler geïnstalleerd wanneer de onLooperPrepared()
wordt aangeroepen. Dat Handler
kan dus geassocieerd worden met dat Looper
.
-
Looper
wordt alleen bereid nadat HandlerThread ‘ sstart()
wordt genoemd, d.w.z. nadat de thread loopt. - A
Handler
kan worden geassocieerd met eenHandlerThread
, alleen nadatLooper
is bereid.
andere manier om de HandlerThread aan te maken:
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");handlerThread.start();Handler handler = new Handler(handlerThread.getLooper());
opmerking: HandlerThread moet myHandlerThread.quit()
aanroepen om de bronnen vrij te maken en de uitvoering van de thread te stoppen.
ik stel voor de bovenstaande codes te oefenen, zodat u hun kleine details kunt begrijpen.
ik heb een voorbeeldproject gemaakt voor simulatie van postkantoren. Postkantoor is gebouwd op HandlerThread en klanten communiceren met de hulp van het postkantoor. Een Simulator klasse creëert weinig Client Bots en delegeren hun communicatie naar de hoofdactiviteit, die maakt het in een live feed.
de link naar dit voorbeeld
ik heb ook een video tutorial gemaakt voor dit onderwerp, en ik raad ten zeerste aan om het te bekijken. Klik hier om nu te bekijken.
laten we ook vrienden worden op Twitter, Linkedin, GitHub en Facebook.
leren is een reis, laten we samen leren!