GUI bijwerken: uitvoerbare bestanden versus berichten

Om de GUI vanuit andere threads bij te werken, zijn er in principe twee hoofdbenaderingen:

  1. Gebruik java.lang.Runnable met een van deze methoden:

    Activity.runOnUiThread(Runnable)
    View.post(Runnable)
    View.postDelayed(Runnable, long)
    Handler.post(Runnable)
    
  2. Gebruik android.os.Message:

    Handler.sendMessage(Message) / Handler.handleMessage(Message)
    

Je kunt ook AsyncTask gebruiken, maar mijn vraag is meer gericht op het gebruik van een heel eenvoudig onderdeel. Laten we eens kijken hoe het zou worden gedaan met beide benaderingen:

  1. Uitvoerbare bestanden gebruiken:

    TextViev tv = ...;
    final String data = "hello";
    Runnable r = new Runnable() {
        @Override
        public void run(){
            tv.setText(data);
        }
    };
    //Now call Activity.runOnUiThread(r) or handler.post(r), ...
    
  2. Berichten gebruiken:

    Message m = handler.obtainMessage(UPDATE_TEXT_VIEW, "hello");
    handler.sendMessage(m);
    //Now on handler implementation:
        @Override
        public void handleMessage(Message msg) {
            if(msg.what == UPDATE_TEXT_VIEW){
                String s = (String) msg.obj;
                tv.setText(data);
            } ... //other IFs?
        }
    

IMHO, Berichten zijn niet de juiste keuze omdat:

  • Niet gemakkelijk te begrijpen voor nieuwe niet-android-programmeurs (handler haakt aan de draad tijdens de constructie).
  • De payload van het object moet Parcellable zijn als het bericht de procesgrenzen overschrijdt.
  • Berichten worden hergebruikt (foutgevoelig als ze niet goed worden opgeschoond?)
  • De handler heeft een dubbele rol (hij verzendt berichten, maar behandelt ze ook)
  • Berichtkenmerken zijn openbaar, maar bieden ook getter/setter.

Aan de andere kant volgen Runnables het bekende commandopatroon en zijn ze programmeervriendelijker en leesbaarder.

Dus wat zijn de voordelen van het gebruik van Berichten boven Runnables? Worden berichten naar de achtergrond geduwd in moderne Android-programmering? Is er iets dat u met Berichten kunt doen wat niet met Runnables kan?

Bij voorbaat dank.


Antwoord 1, autoriteit 100%

Ik zou zeggen dat er weinig verschil is tussen het gebruik van een Messageversus een Runnable. Het zal vooral neerkomen op persoonlijke voorkeur. Waarom? Als je naar de broncode kijkt, zul je zien dat het plaatsen van een Runnableexact hetzelfde berichtmechanisme gebruikt. Het voegt eenvoudig de Runnabletoe aan een Messageen verzendt dat.

4.4.2 Broncode

public final boolean post(Runnable r) {
    return  sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

Ref: Grep-code – Handler


Antwoord 2, autoriteit 68%

Messageskunnen opnieuw worden gebruikt, zodat er minder objecten worden gemaakt en minder GC. Je krijgt ook minder lessen en anonieme typen.

Een groot voordeel is dat een klas die een Messagenaar een Handlerstuurt, niets hoeft te weten over de implementatie van die Message. Dat kan helpen bij inkapseling, afhankelijk van waar het wordt gebruikt.

Overweeg ten slotte het verschil in netheid tussen

mHandler.obtainMessage(DO_STUFF, foo).sendToTarget();

vs

final Foo tempFoo = foo;
mHandler.post(new Runnable(){
    @Override
    public void run(){
        doStuff(tempFoo);
    }
};

Als u meerdere plaatsen heeft waar u doStuff()zou moeten gebruiken, is de eerste VEEL leesbaarder en heeft u minder codeduplicatie.


Antwoord 3, autoriteit 18%

Handler-interface biedt veel meer functionaliteit dan runOnUiThread(), volgens docs:

Een Handler kan op twee manieren worden gebruikt:
(1) om berichten en runnables te plannen die op een bepaald moment in de toekomst moeten worden uitgevoerd
(2) om een ​​actie in een wachtrij te plaatsen die moet worden uitgevoerd op een andere thread dan de uwe.

runOnUiThreaddoet alleen een subset van (2). dat wil zeggen “een actie in de wachtrij plaatsen die moet worden uitgevoerd op UI-thread

Dus IMO, tenzij je die extra functies nodig hebt, is runOnUiThreadvoldoende en heeft de voorkeur.


Antwoord 4, autoriteit 9%

Ik geef de voorkeur aan Runnableboven Message. Ik denk dat code die Runnablegebruikt veel duidelijker is dan Message, omdat de gebeurtenisafhandelingscode heel dicht bij de gebeurtenis ligt. U kunt ook de overhead van het definiëren van constanten en schakelen tussen gevallen vermijden.

En ik denk niet dat het gebruik van Runnablede inkapseling schendt. U kunt de code in Runnable.run()extraheren in een andere methode in de outer class, bijvoorbeeld on...Event(), of zelfs in een EventHandler-object. Beide manieren zijn veel duidelijker dan het gebruik van Message, vooral wanneer je winkelverwijzingen nodig hebt in Message, omdat het gebruik van Runnabledowncasting van msg.obj. En het naamloze veld msg.objis ook foutgevoelig en soms inefficiënt om te begrijpen.

En Runnablekan ook opnieuw worden gebruikt door het op te slaan als een veld.

Other episodes