2016-07-13 13 views
3

Es gibt ein Stück Code, wo ich postDelayed und einige andere Code auf den Haupt-Thread ausgeführt. Ich lief es ein paar Mal und sah immer die folgende Ausgabe:Wann werden in postDelayed veröffentlichte Runnables tatsächlich auf Android ausgeführt?

07-13 14: 22: 18,511 15.376-15.376/sample1.com.sample_1 D/MainActivity: i = 0

.. ..

07-13 14: 22: 15.376 bis 15.376 18,601/sample1.com.sample_1 D/MainActivity: onResume 07-13 14: 22: 15.376 bis 15.376 18,601/sample1.com.sample_1 D/MainActivity : postDelayed

Wie ich Aus der Log-Ausgabe ist es nicht wichtig, dass meine Verzögerung 50 ms beträgt. Die Nachricht "postDelayed" wird nach ca. 100 ms (601 - 511 = 90) getippt. Es sieht so aus, als ob das verzögerte Runnable am Ende der Nachrichtenwarteschlange meines UI-Threads hinzugefügt wird. Aber gibt es irgendeine Garantie dafür, wann genau postDelayed getippt wird? Kann es in der Mitte der for-Schleife eingegeben werden?

package sample1.com.sample_1; 

import android.os.Bundle; 
import android.os.Handler; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 

public class MainActivity extends AppCompatActivity { 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     new Handler().postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       Log.d("MainActivity", "postDelayed"); 
      } 
     }, 10); 
     for (int i = 0; i < 10000; i++) { 
      Log.d("MainActivity", "i = " + i); 
     } 
    } 

    @Override 
    protected void onResume() { 
     Log.d("MainActivity", "onResume"); 
     super.onResume(); 

    } 
} 
+0

Android beschränkt die UI-Operation im Haupt-Thread ist, um die Dinge zu verhindern, die Sie tun möchten. – Harlan

+0

@Harlon, ich bin mir nicht sicher, ob ich dich verstanden habe. –

Antwort

2

Es gibt auch Protokolle von anderen Diensten und Anwendungen, daher ist die Berechnung der Handler-Verzögerung basierend auf der Protokollausgabe nicht korrekt. Der Logging-Mechanismus des Android verfügt über eine eigene Warteschlange, sodass Ihre Nachricht aufgrund anderer Protokolle in der Warteschlange möglicherweise verzögert wird.

Mein Vorschlag wäre System.nanoTime(), um die Zeit zwischen Handler Verzögerungen zu berechnen. Soweit ich weiß, gibt es den genauesten Timer-Wert.

Schließlich, um Ihre Frage zu beantworten, nein können Sie nicht genau die Zeit, wann eine Aktion stattfinden wird. Es gibt Tausende (wenn nicht Millionen) verschiedener Bedingungen, die Aktionen Ihrer Anwendung verzögern können, insbesondere wenn es sich um eine asynchrone Aktion handelt.

Edit: Diese Verzögerung kann nicht genau 50ms Verzögerung garantieren, aber es kann "mindestens" 50ms Verzögerung garantieren.

+0

Ja, es sieht aus wie 'postDelayed (r, 10)' garantiert mindestens 10 ms. Hier ist ein Beispiel mit NanoTime https://gist.github.com/anonymous/70f301a06959f91b96302d6a6adddd6d –

+0

07-13 17: 58: 36,391 30902-30902/Beispiel1.com.sample_1 D/MainActivity: timeHandler = 22583545657183 07-13 17: 58: 36.281 30902-30902/sample1.com.sample_1 D/MainActivity: beforeTimeHandler = 22583437099224 Das Diff ist 108557959 Nanosec = 10 ms (ungefähr) –

0

Verwendung post() nennen tatsächlich sendMessageDelayed(getPostMessage(r), 0) und postDelayed() wird sendMessageDelayed(getPostMessage(r), delayMillis) nennen, sie ähnlich sind.

die post...() Methoden werden schließlich queue.enqueueMessage aufrufen, anders bei when param, es entscheidet, wo die Nachricht in die Nachrichtenwarteschlange eingefügt wird. Sie können die Nachricht in der Warteschlange ändern, aber die Nachricht kann nicht unterbrochen werden.

1

Nachdem der Code für Handler.postDelay() nach unten verfolgt wurde, sieht es schließlich wie MessageQueue.enqueueMessage() heißt. Aus dem Code scheint es die Nachrichtenwarteschlange unendlich zu durchlaufen, bis es das Ende erreicht oder bis die aktuelle Aufgabenzeit höher als unsere Verzögerungszeit ist und dann die Aufgabe an dieser Position in der Warteschlange einfügt. Dies bedeutet, dass die Warteschlange vor der Ausführung Ihrer Aufgabe sehr lange dauert. Sie sollten Ihre Aufgabe weniger oder weniger innerhalb weniger Millisekunden ausführen, wenn Sie dies wünschen.

Ich vermute, dass Ihre Operationen sind nicht das Problem, sondern, das Android ist beschäftigt mit dem Haupt-Thread Rendering Ihrer Benutzeroberfläche und andere interne Jobs, was ist, was Ihre Aufgabe verzögert. Vermutlich wurde die Ausführung des gesamten Codes in onCreate, onStart, onResume für Ihre Aktivität und die Klassen, die er erweitert hat, in die Warteschlange vor Ihrer PostDelay-Zeit + 10ms gestellt.

100ms ist etwa 6 Frames, so könnte es nur die Zeit für die Anzeige der Benutzeroberfläche Ihrer Aktivität sein, versuchen Sie Ihre postDelay auf einen Knopf klicken statt, ich glaube, die Zeit wird viel vorhersehbarer sein als die UI und Activity sind nicht eingerichtet oder abgerissen werden.

+0

07-13 17: 49: 45.781 14332-14332/sample1.com.sample_1 D/MainActivity: i = 0 ..... 07-13 17: 49: 45,871 14.332-14.332/sample1.com.sample_1 D/MainActivity: postDelayed Es sieht aus wie Sie den Code auf eine Schaltfläche klicken bewegen macht keinen Unterschied –