Ich habe einen Worker-Thread, der ein runnable-Objekt erstellt und runOnUiThread darauf aufruft, weil er sich mit Ansichten und Steuerelementen beschäftigt. Ich möchte das Ergebnis der Arbeit des runnable-Objekts sofort verwenden. Wie kann ich warten, bis es fertig ist? Es stört mich nicht, wenn es blockiert ist.
Antworten
Zu viele Anzeigen?Das ist vielleicht ein wenig simpel, aber ein Mutex wird die Aufgabe erfüllen:
final Semaphore mutex = new Semaphore(0);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
// YOUR CODE HERE
mutex.release();
}
});
try {
mutex.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
Eine Lösung könnte die Nutzung der Java-Funktion FutureTask<T>
was den Vorteil hat, dass sich bereits jemand anderes für Sie um alle potenziellen Gleichzeitigkeitsprobleme gekümmert hat:
public void sample(Activity activity) throws ExecutionException, InterruptedException {
Callable<Void> callable = new Callable<Void>() {
@Override
public Void call() throws Exception {
// Your task here
return null;
}
};
FutureTask<Void> task = new FutureTask<>(callable);
activity.runOnUiThread(task);
task.get(); // Blocks
}
Sie können sogar ein Ergebnis aus dem Haupt-Thread zurückgeben, indem Sie die Void
mit etwas anderem.
Andrew Antwort ist gut, ich eine Klasse für eine einfachere Nutzung erstellen.
Implementierung der Schnittstelle :
/**
* Events for blocking runnable executing on UI thread
*
* @author
*
*/
public interface BlockingOnUIRunnableListener
{
/**
* Code to execute on UI thread
*/
public void onRunOnUIThread();
}
Implementierung der Klasse :
/**
* Blocking Runnable executing on UI thread
*
* @author
*
*/
public class BlockingOnUIRunnable
{
// Activity
private Activity activity;
// Event Listener
private BlockingOnUIRunnableListener listener;
// UI runnable
private Runnable uiRunnable;
/**
* Class initialization
* @param activity Activity
* @param listener Event listener
*/
public BlockingOnUIRunnable( Activity activity, BlockingOnUIRunnableListener listener )
{
this.activity = activity;
this.listener = listener;
uiRunnable = new Runnable()
{
public void run()
{
// Execute custom code
if ( BlockingOnUIRunnable.this.listener != null ) BlockingOnUIRunnable.this.listener.onRunOnUIThread();
synchronized ( this )
{
this.notify();
}
}
};
}
/**
* Start runnable on UI thread and wait until finished
*/
public void startOnUiAndWait()
{
synchronized ( uiRunnable )
{
// Execute code on UI thread
activity.runOnUiThread( uiRunnable );
// Wait until runnable finished
try
{
uiRunnable.wait();
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
}
}
Verwendung:
// Execute an action from non-gui thread
BlockingOnUIRunnable actionRunnable = new BlockingOnUIRunnable( yourActivity, new BlockingOnUIRunnableListener()
{
public void onRunOnUIThread()
{
// Execute your activity code here
}
} );
actionRunnable.startOnUiAndWait();
Ich denke, der einfachste Weg, dies zu erreichen, ist die Verwendung eines "CountDownLatch".
final CountDownLatch latch = new CountDownLatch(1);
runOnUiThread(new Runnable() {
@Override
public void run() {
// Do something on the UI thread
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Now do something on the original thread
(Ich glaube, diese Frage ist ein Duplikat von " Wie man Timer-Task zu warten, bis runOnUiThread abgeschlossen ")
- See previous answers
- Weitere Antworten anzeigen