Ausführen von Code im Hauptthread von einem anderen Thread
Lesezeit: 6 Minuten
Ahmed
In einem Android-Dienst habe ich Threads erstellt, um einige Hintergrundaufgaben zu erledigen.
Ich habe eine Situation, in der ein Thread eine bestimmte Aufgabe in der Nachrichtenwarteschlange des Hauptthreads veröffentlichen muss, zum Beispiel a Runnable.
Gibt es einen Weg zu bekommen Handler des Hauptthreads und Posts Message/Runnable dazu aus meinem anderen Thread?
Sie können auch einen benutzerdefinierten Rundfunkempfänger verwenden …. versuchen Sie meine Antwort hier, [Inner Broadcast Receiver][1] [1]: stackoverflow.com/a/22541324/1881527
– Melbourne Lopes
21. März 2014 um 9:29 Uhr
Es gibt viele Wege. Abgesehen von Davids Antwort und dzeikeis Kommentar in seiner Antwort können Sie (3) einen Broadcast-Empfänger verwenden oder (4) den Handler in Extras von Intent übergeben, der zum Starten des Dienstes verwendet wird, und dann den Handler des Hauptthreads innerhalb des Dienstes mit getIntent () abrufen. ).getExtras() .
– Ashok Bijoy Debnath
4. Dezember 2014 um 8:37 Uhr
@sazzad-hissain-khan, Warum diese Frage aus dem Jahr 2012 mit den meisten Antworten in Java mit dem Kotlin-Tag markieren?
– Tenfour04
7. August 2019 um 18:45 Uhr
David Wasser
HINWEIS: Diese Antwort hat so viel Aufmerksamkeit erregt, dass ich sie aktualisieren muss. Seit die ursprüngliche Antwort gepostet wurde, hat der Kommentar von @dzeikei fast so viel Aufmerksamkeit auf sich gezogen wie die ursprüngliche Antwort. Also hier 2 mögliche Lösungen:
1. Wenn Ihr Hintergrund-Thread einen Verweis auf a Context Objekt:
Stellen Sie sicher, dass Ihre Worker-Threads im Hintergrund Zugriff auf ein Kontextobjekt haben (das kann der Anwendungskontext oder der Dienstkontext sein). Dann tun Sie dies einfach im Hintergrund-Worker-Thread:
// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {....} // This is your code
};
mainHandler.post(myRunnable);
2. Wenn Ihr Hintergrund-Thread a Context Objekt
(empfohlen von @dzeikei):
// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {....} // This is your code
};
mainHandler.post(myRunnable);
Danke David, es hat für mich geklappt, noch eine Sache, wenn Sie mir helfen könnten, wenn ich Handler und impl handleMessage() erweitere, würde es den Hauptthread daran hindern, seine Nachrichten zu verarbeiten? das ist nur eine frage aus neugier..
– Ahmed
20. Juni 2012 um 19:03 Uhr
Nein. Wenn Sie eine Unterklasse bilden Handler (oder verwenden Handler.Callback Schnittstelle) Ihre handleMessage() -Methode wird NUR für Nachrichten aufgerufen, die mit Ihrem Handler gepostet wurden. Der Haupt-Thread verwendet einen anderen Handler zum Posten/Verarbeiten von Nachrichten, sodass es keinen Konflikt gibt.
– David Wasser
20. Juni 2012 um 19:22 Uhr
Ich glaube, Sie brauchen nicht einmal Kontext, wenn Sie verwenden Handler mainHandler = new Handler(Looper.getMainLooper());
– dzeikei
5. November 2013 um 3:57 Uhr
Kleiner Punkt; Ihr Code geht nicht dorthin, wo … derzeit ist. Es sollte sein new Runnable(){@Override public void run() {....}};
– Richard Tingle
31. Juli 2014 um 10:19 Uhr
@SagarDevanga Dies ist nicht der richtige Ort, um eine andere Frage zu stellen. Bitte stellen Sie eine neue Frage, keinen Kommentar zu einer nicht verwandten Antwort. Auf diese Weise erhalten Sie eine bessere und schnellere Antwort.
– David Wasser
21. Januar 2015 um 9:10 Uhr
Alexej Wassiljew
Wie ein Kommentator unten richtig angedeutet hat, ist dies keine allgemeine Lösung für Dienste, sondern nur für Threads, die von Ihrer Aktivität gestartet werden (ein Dienst kann ein solcher Thread sein, aber nicht alle). Lesen Sie zum komplizierten Thema der Serviceaktivitätskommunikation bitte den gesamten Serviceabschnitt des offiziellen Dokuments – es ist komplex, daher lohnt es sich, die Grundlagen zu verstehen: http://developer.android.com/guide/components/services.html#Benachrichtigungen
Die folgende Methode kann in den einfachsten Fällen funktionieren:
Wenn ich Sie richtig verstehe, benötigen Sie einen Code, der im GUI-Thread der Anwendung ausgeführt werden muss (ich kann an nichts anderes denken, das als “Haupt” -Thread bezeichnet wird). Dafür gibt es eine Methode auf Activity:
someActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
//Your code to run in GUI thread here
}//public void run() {
});
OP sagt, er führt Threads in a aus Service. Sie können nicht verwenden runOnUiThread() in einem Service. Diese Antwort ist irreführend und geht nicht auf die gestellte Frage ein.
– David Wasser
27. November 2013 um 9:25 Uhr
Sazzad Hissain Khan
Kotlin-Versionen
Wann Sie befinden sich in einer Aktivitätdann benutze
runOnUiThread {
//code that runs in main
}
Wann Sie haben einen AktivitätskontextmContext dann verwenden
mContext.runOnUiThread {
//code that runs in main
}
Wenn du irgendwo wo bist kein Kontext vorhandendann benutze
Handler(Looper.getMainLooper()).post {
//code that runs in main
}
Ich bin mir nicht sicher, welche Version von Kotlin das ist, aber ich musste Klammern hinzufügen: runOnUiThread(){...}
– Wex
14. Mai 2020 um 9:20 Uhr
Funktioniert hervorragend für mich mit Android Studio 4.1.1 auf dem Mac.
– Goldener Daumen
12. Dezember 2020 um 0:30 Uhr
Thema_Mann
Es gibt einen anderen einfachen Weg, wenn Sie keinen Zugriff auf den Kontext haben.
1). Erstellen Sie einen Handler aus dem Hauptlooper:
Handler uiHandler = new Handler(Looper.getMainLooper());
2). Implementieren Sie eine lauffähige Schnittstelle:
Runnable runnable = new Runnable() { // your code here }
3). Posten Sie Ihr Runnable im uiHandler:
uiHandler.post(runnable);
Das ist alles 😉 Viel Spaß mit Threads, aber vergessen Sie nicht, sie zu synchronisieren.
Wenn Sie Code in einem Thread ausführen, z. B. eine Aktion verzögern, müssen Sie aufrufen runOnUiThread aus dem Kontext. Zum Beispiel, wenn Ihr Code drin ist MainActivity Klasse dann verwenden Sie dies:
@GregBrown Wie Sie durch Ihren Link zu angegeben haben Activity Dokumentation, runOnUiThread() ist eine Methode der Activity. Es ist keine Methode der Service, daher können Sie es nicht verwenden. Was könnte klarer sein als das?
– David Wasser
4. August 2016 um 16:41 Uhr
@DavidWasser Fair genug. Ich weiß nicht einmal mehr, warum ich diese Frage jetzt gestellt habe (sie wurde vor fast einem Jahr gepostet).
– Gregor Brown
7. August 2016 um 20:42 Uhr
Matt Lacey
Ein komprimierter Codeblock lautet wie folgt:
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// things to do on the main thread
}
});
Dies beinhaltet nicht die Weitergabe der Aktivitätsreferenz oder der Anwendungsreferenz.
Kotlin-Äquivalent:
Handler(Looper.getMainLooper()).post(Runnable {
// things to do on the main thread
})
OP sagt, er führt Threads in a aus Service. Sie können nicht verwenden runOnUiThread() in einem Service.
@GregBrown Wie Sie durch Ihren Link zu angegeben haben Activity Dokumentation, runOnUiThread() ist eine Methode der Activity. Es ist keine Methode der Service, daher können Sie es nicht verwenden. Was könnte klarer sein als das?
– David Wasser
4. August 2016 um 16:41 Uhr
@DavidWasser Fair genug. Ich weiß nicht einmal mehr, warum ich diese Frage jetzt gestellt habe (sie wurde vor fast einem Jahr gepostet).
– Gregor Brown
7. August 2016 um 20:42 Uhr
Inn0vative1
Der einfachste Weg, besonders wenn Sie keinen Kontext haben, wenn Sie RxAndroid verwenden, können Sie Folgendes tun:
Sie können auch einen benutzerdefinierten Rundfunkempfänger verwenden …. versuchen Sie meine Antwort hier, [Inner Broadcast Receiver][1] [1]: stackoverflow.com/a/22541324/1881527
– Melbourne Lopes
21. März 2014 um 9:29 Uhr
Es gibt viele Wege. Abgesehen von Davids Antwort und dzeikeis Kommentar in seiner Antwort können Sie (3) einen Broadcast-Empfänger verwenden oder (4) den Handler in Extras von Intent übergeben, der zum Starten des Dienstes verwendet wird, und dann den Handler des Hauptthreads innerhalb des Dienstes mit getIntent () abrufen. ).getExtras() .
– Ashok Bijoy Debnath
4. Dezember 2014 um 8:37 Uhr
@sazzad-hissain-khan, Warum diese Frage aus dem Jahr 2012 mit den meisten Antworten in Java mit dem Kotlin-Tag markieren?
– Tenfour04
7. August 2019 um 18:45 Uhr