thread runonuithread method cannot java android multithreading

java - method - cómo esperar a que se complete Android runOnUiThread?



runonuithread(() (6)

Tengo un hilo de trabajo que crea un objeto ejecutable y ejecuta runOnUiThread en él, porque trata con vistas y controles. Me gustaría usar el resultado del trabajo del objeto ejecutable de inmediato. ¿Cómo espero a que termine? No me molesta si está bloqueando.


Creo que la forma más sencilla de lograr esto es usar un "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

(Creo que esta pregunta es un duplicado de " Cómo hacer que la tarea del temporizador espere hasta que finalice runOnUiThread ")


La respuesta de Andrew es buena, creo una clase para un uso más fácil.

Implementación de interfaz:

/** * Events for blocking runnable executing on UI thread * * @author * */ public interface BlockingOnUIRunnableListener { /** * Code to execute on UI thread */ public void onRunOnUIThread(); }

Implementación de clase:

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

Utilizándolo:

// Execute an action from non-gui thread BlockingOnUIRunnable actionRunnable = new BlockingOnUIRunnable( yourActivity, new BlockingOnUIRunnableListener() { public void onRunOnUIThread() { // Execute your activity code here } } ); actionRunnable.startOnUiAndWait();


Solo arañar los aspectos más destacados

synchronized( myRunnable ) { activity.runOnUiThread(myRunnable) ; myRunnable.wait() ; // unlocks myRunable while waiting }

Mientras tanto ... en myRunnable ...

void run() { // do stuff synchronized(this) { this.notify(); } }


Tal vez un poco simplista, pero un mutex hará el trabajo:

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


Una solución podría ser aprovechar FutureTask<T> Java, que tiene el beneficio de que otra persona ya ha tratado con todos los posibles problemas de concurrencia:

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 }

Incluso puede devolver un resultado del hilo principal al reemplazar el Void con algo más.