Esperando que se complete un Runnable antes de ejecutar otro Runnable
Tengo una aplicación de Android con una actividad de pestaña principal y varias actividades dentro de las pestañas individuales. En onCreate () de mi actividad principal, tengo un runnable que crea una lista, y en las actividades individuales, hago uso de esta lista.
En el onCreate () de las actividades individuales, también tengo Runnables que operan en la lista. Sin embargo, necesito que estos Runnables se ejecuten sólo cuando Runnable de la actividad de la pestaña principal termine de crear la lista, de lo contrario tendría una lista nula. Estoy tratando de encontrar una manera elegante de hacer esto. En este momento, en Runnable de mi actividad principal, estoy configurando una variable booleana global isDone, y en Runnable de mi actividad individual, espero que isDone se establezca a través de un bucle while. Esto funciona, pero probablemente no es la mejor manera de hacerlo.
- ¿Puedo almacenar archivos de imagen en firebase usando la API de Java?
- Análisis de la cadena JSON en android
- ¿Existe una manera de implementar en caliente los cambios delta en un dispositivo Android?
- DisplayMessageActivity no se puede resolver a un tipo de construcción de la primera aplicación android
- Cómo agregar datos en secuencia de caracteres dinámicamente en java?
¿Alguna idea?
Gracias.
Edit: Estoy intentando el siguiente código, pero estoy recibiendo errores de tiempo de ejecución:
En el Runnable de mi MainActivity:
mainRunnable = new Runnable() { public void run() { try { generateList(); synchronized(this) { listDone = true; notifyAll(); } } catch (Exception e) { Log.e("BACKGROUND_PROC", e.getMessage()); } } }; Thread thread = new Thread(null, mainRunnable, "Background"); thread.start();
En Runnable de mi OtrosActividad:
otherRunnable = new Runnable() { public void run() { synchronized(MainActivity.mainRunnable) { if (!MainActivity.getListDone()) { try { wait(); } catch (InterruptedException e) { } } } } }; Thread thread = new Thread(null, otherRunnable, "Background"); thread.start();
El mainRunnable parece ejecutarse completamente, pero el otherRunnable parece provocar que la aplicación se bloquee. Consigo el mensaje de error siguiente:
01-10 15:41:25.543: E/WindowManager(7074): Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40539850 that was originally added here 01-10 15:41:25.543: E/WindowManager(7074): android.view.WindowLeaked: Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40539850 that was originally added here
- Ejecución Animación y conmutador de imágenes al mismo tiempo
- ¿Qué es "estructura de datos pasiva" en Android / Java?
- java.lang.NullPointer Excepción en getResources (). getString (R.string.value);
- ¿Cómo puedo optimizar este código que contiene alguna línea repetitiva?
- Problemas con ProGuard para Android con Parse 1.3.5 jar
- Android ActionBar no visible
- ¿Quién está agregando "\ n" en la imagen codificada en Base64 cuando la escribo en un archivo? Java
- Java.util.ConcurrentModificationException en las pruebas de JUnit
Puede utilizar los métodos wait
y notify
.
Para ello, debe haber algún objeto accesible a nivel mundial cuyo bloqueo no se utilice en ninguna otra parte del programa en este momento. Estoy asumiendo que la creación de lista Runnable
sí mismo puede desempeñar este papel.
Así que puedes añadir algo como esto a la clase Runnable
crea Runnable
:
private boolean listsDone = false; boolean getListsDone() { return listsDone; }
Y algo así a su método run()
, inmediatamente después de haber creado las listas:
synchronized (this) { listsDone = true; notifyAll(); }
Y algo así a los demás Runnable
s ' run()
métodos, en el punto donde tienen que esperar:
synchronized (listCreatingRunnableObject) { if (!listCreatingRunnableObject.getListsDone()) { try { listCreatingRunnableObject.wait(); } catch (InterruptedException e) { // handle it somehow } } }
Actualización: Para aclarar, ambos bloques synchronized
necesitan ser sincronizados sobre el mismo objeto, y usted tiene que llamar wait()
y notifyAll()
en ese objeto. Si el objeto es Runnable
, puede estar implícito para el primero (como en el código anterior), pero si es la actividad, debe utilizar explícitamente el objeto de actividad en ambos casos.
Bah. Estas respuestas son demasiado complicadas. Utilice una cola como esta:
public class RunQueue implemements Runnable { private List list = new ArrayList(); public void queue(Runnable task) { list.add(task); } public void run() { while(list.size() > 0) { Runnable task = list.get(0); list.remove(0); task.run(); } } }
Esto le permite usar un hilo en lugar de varios hilos. Además, puede mantener todos los objetos "Runnable" existentes al mismo tiempo que limpia cualquier código que tenga para las esperas y las combinaciones.
Configure un CountDownLatch con un valor de 1 en el hilo principal, y luego haga que los subprocesos dependientes lo esperen. Cuando el hilo principal está hecho, contando hacia abajo el pestillo a 0 y los camareros comenzará a la derecha hacia arriba.
Una espera activa utilizando un bucle while no es una buena idea en absoluto. Lo más simple sería que el primer Runnable acabara de encender el resto de ellos como su último paso. Si eso no se puede hacer que funcione por alguna razón, eche un vistazo a la publicación de un mensaje a un manejador.
¿Hay alguna razón por la que está utilizando Runnable
s y no Thread
s? Si utiliza Thread
s, puede utilizar las diversas primitivas de comunicación de subprocesos que existen por este motivo exacto ( wait()
y join()
en particular).
He creado un método auxiliar que contiene todo el código para publicar un runnable y esperar hasta que termine de ejecutarse.
La lógica es similar a lo que @Taymon describe, pero la implementación es más general.
Compruébelo: https://gist.github.com/Petrakeas/ce745536d8cbae0f0761
- Android: ¿Es posible tener múltiples preferencias compartidas por aplicación?
- Toca y arrastra la imagen en android