Ich denke, ich habe eine Implementierung gesehen, die das macht. Die Grundidee ist grob
class UiThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
Sie delegieren können für den Hauptthread, indem es zu einem Handler etwas in dem Haupt-Thread ausgeführt werden.
Edit: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit/android/MainThreadExecutor.java zum Beispiel
Edit2: Sie können den Handler wie z konfigurieren SensorManager#registerListener(..., Handler handler)
können Sie tun.
class HandlerThreadExecutor implements Executor {
private final Handler mHandler;
public HandlerThreadExecutor(Handler optionalHandler) {
mHandler = optionalHandler != null ? optionalHandler : new Handler(Looper.getMainLooper());
}
@Override
public void execute(Runnable command) {
mHandler.post(command);
}
}
Der Vorteil gegenüber dem aktuellen Threads Looper ist, dass es es ausdrücklich macht die Looper
Sie verwenden. In deiner Lösung nimmst du den Looper von welchem Thread auch immer new ExecuteOnCaller()
aufruft - und das ist oft nicht der Thread, in dem du den Code später ausführst.
Ich würde gerne wissen, wie man den gleichen Effekt erzielt, ohne auf die Android-spezifischen Sachen wie Handler und Looper zurückgreifen zu müssen, nur mit reinem Java.
Looper
, Handler
und die Nachrichten-Warteschlange hinter all dieser Logik sind meist reine Java gemacht. Das Problem mit einer generischen Lösung ist, dass Sie Code nicht "injizieren" können, um in einem Thread zu laufen. Der Thread muss regelmäßig eine Art von Aufgabenwarteschlange überprüfen, um festzustellen, ob etwas ausgeführt werden muss.
Wenn Sie Code schreiben, wie
new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("Hello");
}
}
}).start();
Dann gibt es keine Möglichkeit, dass Faden sonst noch etwas zu machen, aber immer wieder drucken „Hallo“. Wenn Sie das tun könnten, wäre es, als würden Sie dynamisch einen Sprung zu anderem Code in den Programmcode einfügen. Das wäre IMO eine schreckliche Idee.
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
Runnable codeToRunInThisThread = queue.take();
codeToRunInThisThread.run();
}
} catch (InterruptedException ignored) {}
}
}).start();
Auf der anderen Seite ist ein einfaches Gewinde, dass immer in einer Warteschlange Schleifen.Der Thread könnte dazwischen andere Aufgaben erledigen, aber Sie müssen dem Code eine manuelle Überprüfung hinzufügen.
Und Sie können es Aufgaben über
queue.put(new Runnable() {
@Override
public void run() {
System.out.println("Hello!");
}
});
senden Es gibt keine spezielle Handler hier definiert, aber das ist der Kern dessen, was Handler & Looper in Android tun. Handler
in Android können Sie einen Rückruf für eine Message
anstelle von nur Runnable
definieren.
Executors.newCachedThreadPool()
und ähnliche tun in etwa die gleiche Sache. Es warten nur mehrere Threads auf Code in einer einzelnen Warteschlange.
Als Erweiterung auf diese Frage ist es möglich, dasselbe zu tun, aber nicht nur mit UI-Thread, aber mit einem bestimmten Thread, in dem der Aufruf von Asynchron-Verfahren hergestellt wird?
Die generische Antwort ist Nein. Nur wenn es eine Möglichkeit gibt, Code in diesen Thread zu injizieren.
Konnte Ihre Frage nicht verstehen! Was ist Executer? Bitte etwas mehr ausarbeiten! Danke –