Wie führe ich einen Runnable-Thread in Android in definierten Intervallen aus?
Lesezeit: 7 Minuten
Rajapandisch
Ich habe eine Anwendung entwickelt, um Text in definierten Intervallen auf dem Bildschirm des Android-Emulators anzuzeigen. Ich benutze die Handler Klasse. Hier ist ein Ausschnitt aus meinem Code:
handler = new Handler();
Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
}
};
handler.postDelayed(r, 1000);
Wenn ich diese Anwendung starte, wird der Text nur einmal angezeigt. Warum?
Ich kann mich nie erinnern, wie man ein Runnable macht, also besuche ich immer Ihren Beitrag, wie es geht :))
– Adrian Sicaru
4. August 2015 um 11:01 Uhr
Lambdas sind jetzt meistens der richtige Weg 😉
– xeruf
2. Juli 2017 um 21:22 Uhr
alex2k8
Die einfache Lösung für Ihr Beispiel ist:
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
Oder wir können zum Beispiel normales Garn verwenden (mit Original Runner):
Sie können Ihr ausführbares Objekt einfach als einen Befehl betrachten, der zur Ausführung an die Nachrichtenwarteschlange gesendet werden kann, und einen Handler nur als ein Hilfsobjekt, das zum Senden dieses Befehls verwendet wird.
Alex, ich habe einen kleinen Zweifel. Jetzt läuft der Thread perfekt und zeigt den Text kontinuierlich an. Wenn ich das stoppen möchte, bedeutet das, was ich tun muss? Bitte hilf mir.
– Rajapandisch
17. Dezember 2009 um 14:19 Uhr
Sie können die boolesche Variable _stop definieren und auf „true“ setzen, wenn Sie anhalten möchten. Und ändern Sie „while(true)“ in „while(!_stop)“, oder wenn das erste Beispiel verwendet wird, ändern Sie einfach in „if(!_stop) handler.postDelayed(this, 1000)“.
– alex2k8
17. Dezember 2009 um 22:01 Uhr
Wenn Sie sicher sein wollen, dass Handler an den Haupt-Thread angehängt wird, sollten Sie ihn wie folgt initialisieren: handler = new Handler(Looper.getMainLooper());
– Yair Kukielka
9. Juli 2015 um 0:20 Uhr
@alex2k8 Sollte es im zweiten Snippet nicht handler.post(r) statt handler.post(this) heißen? Wenn Sie die Lösung mit Thread verwenden möchten, müssen Sie außerdem handler.postDelayed(this, 1000) aus dem Runnable r entfernen, da die Verzögerung bereits innerhalb der Methode run() des Thread-Objekts ausgeführt wird.
– Jerry
14. März 2018 um 14:57 Uhr
@alex2k8 – Hallo Bruder! Bitte sagen Sie mir, wie ich den 2. Snippet stoppen kann Thread manuell während des Laufens?
– Irfan Akram
8. April 2020 um 21:13 Uhr
Benutzer2212515
new Handler().postDelayed(new Runnable() {
public void run() {
// do something...
}
}, 100);
Wenn Sie sicher sein wollen, dass Handler an den Haupt-Thread angehängt wird, sollten Sie ihn wie folgt initialisieren: new Handler(Looper.getMainLooper());
– Yair Kukielka
9. Juli 2015 um 0:23 Uhr
Entspricht diese Lösung nicht dem ursprünglichen Beitrag? Es würde das Runnable nur einmal nach 100 Millisekunden ausführen.
– Tronmann
10. Mai 2018 um 15:38 Uhr
NguyenDat
Ich denke, dass die erste Lösung von Alex2k8 für das Update jede Sekunde verbessert werden kann
1.Originalcode:
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
2. Analyse
Nehmen Sie bei den oben genannten Kosten an tv.append("Hello Word") Kosten T Millisekunden, nach Anzeige 500 mal verspätete Zeit ist 500*T Millisekunden
Es erhöht sich verzögert, wenn es lange läuft
3. Lösung
Um dies zu vermeiden, ändern Sie einfach die Reihenfolge von postDelayed(), um Verzögerungen zu vermeiden:
public void run() {
handler.postDelayed(this, 1000);
tv.append("Hello World");
}
-1 Sie gehen davon aus, dass die Aufgabe, die Sie in run() ausführen, bei jedem Lauf einen konstanten Betrag kostet. Wenn dies eine Operation für dynamische Daten wäre (was normalerweise der Fall ist), würden am Ende mehr als ein run() auftreten Einmal. Aus diesem Grund wird postDelayed normalerweise am Ende platziert.
– Jay
24. Februar 2012 um 0:18 Uhr
@Jay Leider liegst du falsch. Ein Handler ist einem einzelnen Thread (und einem Looper, der die Ausführungsmethode dieses Threads ist) + einer MessageQueue zugeordnet. Jedes Mal, wenn Sie eine Nachricht posten, reihen Sie sie in die Warteschlange ein, und wenn der Looper das nächste Mal die Warteschlange überprüft, führt er die run-Methode des von Ihnen geposteten Runnable aus. Da das alles in nur einem Thread passiert, können Sie nicht mehr als 1 gleichzeitig ausführen lassen. Wenn Sie auch zuerst den PostDelayed ausführen, kommen Sie näher an 1000 ms pro Ausführung heran, da intern die aktuelle Zeit + 1000 als Ausführungszeit verwendet wird. Wenn Sie Code vor den Post setzen, fügen Sie eine zusätzliche Verzögerung hinzu.
– zapl
27. April 2012 um 23:42 Uhr
@zapl danke für den Tipp zum Handler, ich bin davon ausgegangen, dass mehrere Runnables und damit mehrere Threads ausgeführt werden. Intern funktioniert jedoch eine Bedingung wie if ((currenttime – lastruntime)>1000) einwandfrei, wenn die Ausführungsdauer kleiner oder gleich 1000 ms ist. Wenn dies jedoch überschritten wird, wird der Timer sicherlich in nichtlinearen Intervallen auftreten vollständig von der Ausführungszeit der run-Methode abhängig (daher mein Punkt zum unvorhersehbaren Rechenaufwand)
– Jay
3. Mai 2012 um 11:36 Uhr
Wenn Sie einen festen Zeitraum ohne Konflikte wünschen, messen Sie die Startzeit, bevor Sie mit der Arbeit beginnen, und passen Sie Ihre Verzögerung entsprechend an. Sie werden immer noch eine kleine Latenz sehen, wenn die CPU ausgelastet ist, aber es kann Ihnen einen strengeren Zeitraum ermöglichen und erkennen, ob das System überlastet ist (vielleicht um Sachen mit niedriger Priorität zu signalisieren, sich zurückzuziehen).
– Ajax
1. Januar 2013 um 16:29 Uhr
Zar E. Ahmer
Für sich wiederholende Aufgaben können Sie verwenden
new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);
nenne es wie
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
}
},500,1000);
Der obige Code wird danach zum ersten Mal ausgeführt halbe Sekunde (500) und wiederholt sich nach jedem Sekunde (1000)
Woher
Aufgabe die auszuführende Methode ist
nach dem die Zeit bis zur ersten Ausführung
(Intervall die Zeit für die Wiederholung der Ausführung)
Zweitens
Und Sie können auch verwenden CountDownTimer wenn Sie eine Aufgabe mehrmals ausführen möchten.
new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
}
}.start();
//Above codes run 40 times after each second
Und Sie können es auch mit Runnable tun. Erstellen Sie eine lauffähige Methode wie
Runnable runnable = new Runnable()
{
@Override
public void run()
{
}
};
Und nennen Sie es auf diese beiden Arten
new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis // to work on mainThread
ODER
new Thread(runnable).start();//to work in Background
iTech
Ich glaube, für diesen typischen Fall, dh etwas mit einem festen Intervall auszuführen, Timer ist angemessener. Hier ist ein einfaches Beispiel:
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
@Override
public void run() {
// If you want to modify a view in your Activity
MyActivity.this.runOnUiThread(new Runnable()
public void run(){
tv.append("Hello World");
});
}
}, 1000, 1000); // initial delay 1 second, interval 1 second
Verwenden Timer hat wenige vorteile:
Anfängliche Verzögerung und das Intervall können einfach im angegeben werden schedule Funktionsargumente
Der Timer kann durch einfaches Aufrufen gestoppt werden myTimer.cancel()
Wenn Sie nur einen Thread laufen lassen möchten, denken Sie daran, anzurufen myTimer.cancel()Vor Planen eines neuen (wenn myTimer nicht null ist)
Ich glaube nicht, dass ein Timer besser geeignet ist, da er den Android-Lebenszyklus nicht berücksichtigt. Beim Pausieren und Fortsetzen gibt es keine Garantie dafür, dass der Timer korrekt läuft. Ich würde behaupten, dass ein Runnable die bessere Wahl ist.
– Janpan
15. Januar 2014 um 6:27 Uhr
Bedeutet das, dass ein Handler angehalten wird, wenn eine App in den Hintergrund gestellt wird? und wenn es den Fokus wiedererlangt, wird es (mehr oder weniger) weitermachen, als wäre nichts passiert?
– Andreas Gallasch
15. Januar 2015 um 19:53 Uhr
Dzhuneyt
Handler handler=new Handler();
Runnable r = new Runnable(){
public void run() {
tv.append("Hello World");
handler.postDelayed(r, 1000);
}
};
handler.post(r);
Ich glaube nicht, dass ein Timer besser geeignet ist, da er den Android-Lebenszyklus nicht berücksichtigt. Beim Pausieren und Fortsetzen gibt es keine Garantie dafür, dass der Timer korrekt läuft. Ich würde behaupten, dass ein Runnable die bessere Wahl ist.
– Janpan
15. Januar 2014 um 6:27 Uhr
Bedeutet das, dass ein Handler angehalten wird, wenn eine App in den Hintergrund gestellt wird? und wenn es den Fokus wiedererlangt, wird es (mehr oder weniger) weitermachen, als wäre nichts passiert?
– Andreas Gallasch
15. Januar 2015 um 19:53 Uhr
Kotlin
private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
val handler = Handler()
runnable = Runnable {
// do your work
handler.postDelayed(runnable, 2000)
}
handler.postDelayed(runnable, 2000)
}
Java
Runnable runnable;
Handler handler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
// do your work
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
}
Wie führen wir andere Funktionen in Runnable aus?
– Balasubramanian
4. Januar 2021 um 15:21 Uhr
9641300cookie-checkWie führe ich einen Runnable-Thread in Android in definierten Intervallen aus?yes
Ich kann mich nie erinnern, wie man ein Runnable macht, also besuche ich immer Ihren Beitrag, wie es geht :))
– Adrian Sicaru
4. August 2015 um 11:01 Uhr
Lambdas sind jetzt meistens der richtige Weg 😉
– xeruf
2. Juli 2017 um 21:22 Uhr