Ich habe eine Anwendung entwickelt, um Text in definierten Intervallen im Android-Emulatorbildschirm anzuzeigen. Ich verwende 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?
Die einfache Lösung zu Ihrem Beispiel lautet:
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 normalen Thread verwenden (mit Original Runner):
Thread thread = new Thread() {
@Override
public void run() {
try {
while(true) {
sleep(1000);
handler.post(this);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
Sie können Ihr ausführbares Objekt nur als Befehl betrachten, der zur Ausführung an die Nachrichtenwarteschlange gesendet werden kann, und als Handler nur ein Hilfsobjekt, das zum Senden dieses Befehls verwendet wird.
Weitere Details finden Sie hier http://developer.Android.com/reference/Android/os/Handler.html
Ich denke, die erste Lösung von Alex2k8 für das Update kann jede Sekunde verbessert werden
1.Original code:
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
2.Analyse
tv.append("Hello Word")
_ Kosten T Millisekunden beträgt, nachdem 500 die Zeitverzögerung 500 * T Millisekunden beträgt3. Lösung
Um dies zu vermeiden, ändern Sie einfach die Reihenfolge von postDelayed (), um eine Verzögerung zu vermeiden:
public void run() {
handler.postDelayed(this, 1000);
tv.append("Hello World");
}
new Handler().postDelayed(new Runnable() {
public void run() {
// do something...
}
}, 100);
Ich glaube, für diesen typischen Fall, dh etwas mit einem festen Intervall auszuführen, ist Timer
geeigneter. 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
Die Verwendung von Timer
hat einige Vorteile:
schedule
angegeben werdenmyTimer.cancel()
gestoppt werden.myTimer.cancel()
vorher einen neuen einzuplanen (wenn myTimer nicht null ist)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 zum ersten Mal nach eine halbe Sekunde (500) ausgeführt und wiederholt sich nach jeder Sekunde (1000)
Woher
task ist die auszuführende Methode
after die Zeit bis zur ersten Ausführung
( Intervall Zeit für die Wiederholung der Ausführung)
Zweitens
Sie können auch CountDownTimer verwenden, wenn Sie eine Task mehrfach 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 du kannst es auch mit Run machen. Erstellen Sie eine ausführbare Methode wie
Runnable runnable = new Runnable()
{
@Override
public void run()
{
}
};
Und nennen Sie es auf beiden Wegen
new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis // to work on mainThread
ODER
new Thread(runnable).start();//to work in Background
Handler handler=new Handler();
Runnable r = new Runnable(){
public void run() {
tv.append("Hello World");
handler.postDelayed(r, 1000);
}
};
handler.post(r);
Wenn ich die Dokumentation der Handler.post () -Methode richtig verstanden habe:
Bewirkt, dass Runnable R der Nachrichtenwarteschlange hinzugefügt wird. Das ausführbare Programm wird auf dem Thread ausgeführt, an den dieser Handler angehängt ist.
Die von @ alex2k8 bereitgestellten Beispiele sind zwar nicht korrekt, sie sind jedoch nicht identisch .. __ Wenn Handler.post()
verwendet wird, werden keine neuen Threads erstellt. Sie geben einfach Runnable
in den Thread mit Handler
ein, um von EDT ..__ ausgeführt zu werden. Danach führt EDT nur Runnable.run()
aus, sonst nichts.
Denken Sie daran: Runnable != Thread
.
Ein interessantes Beispiel ist, dass Sie kontinuierlich einen Zähler/Stoppuhr in einem separaten Thread sehen können. Zeigt auch die GPS-Position an. Während der Hauptaktivität ist der Benutzeroberflächen-Thread bereits vorhanden.
Auszug:
try {
cnt++; scnt++;
now=System.currentTimeMillis();
r=Rand.nextInt(6); r++;
loc=lm.getLastKnownLocation(best);
if(loc!=null) {
lat=loc.getLatitude();
lng=loc.getLongitude();
}
Thread.sleep(100);
handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {
Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}
Den Code finden Sie hier:
in Kotlin können Sie jetzt Threads folgendermaßen ausführen:
class SimpleRunnable: Runnable {
public override fun run() {
println("${Thread.currentThread()} has run.")
}
}
fun main(args: Array<String>) {
val thread = SimpleThread()
thread.start() // Will output: Thread[Thread-0,5,main] has run.
val runnable = SimpleRunnable()
val thread1 = Thread(runnable)
thread1.start() // Will output: Thread[Thread-1,5,main] has run
}
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)
}
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);
}