54 Stimmen

wie zu warten, bis Android runOnUiThread beendet ist?

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.

67voto

Andrew Punkte 2484

Nur die Highlights herausgegriffen

synchronized( myRunnable ) {
   activity.runOnUiThread(myRunnable) ;

   myRunnable.wait() ; // unlocks myRunable while waiting
}

In der Zwischenzeit... in myRunnable...

void run()
{
   // do stuff

   synchronized(this)
   {
      this.notify();
   }
}

18voto

DDD Punkte 1452

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();
}

12voto

aha Punkte 3592

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.

10voto

olivier_sdg Punkte 1508

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();

4voto

chetbox Punkte 1562

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 ")

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X