2012-03-30 16 views
6

En mi pequeña aplicación, recibo una serie de cola onEventXXX(), del sistema (no controlada por mí).Método óptimo para posponer onEvent?

El tiempo de los que están enEventXXX() no está garantizado. Lo único garantizado es que se reciben en el pedido en el que se colocaron en la cola.

Dentro de onEventXXX() Tengo que iniciar una operación (O) que no se puede iniciar mientras está pasando otro proceso (P).

Pero no puedo descartar esta "activación de una operación (O)". Debo esperar hasta que el proceso (P) esté completo, y luego prenderlo.

IOW, tengo que poner en cola o al menos posponer esa "activación de una operación" hasta que se complete ese proceso (P).

Mi idea inmediata de la aplicación de esto fue que, en vez de disparar la operación (O), lo haría:

  1. iniciar un temporizador de un solo disparo que comprobar periódicamente el proceso (P)
  2. Cuando transcurre el temporizador, si el proceso (P) no está completo, inicie el tiempo (sí mismo) nuevamente.
  3. Cuando el temporizador haya transcurrido, si el proceso (P) está completo, inicie la operación (O).

Pero conociendo la riqueza de Android, sospecho que hay una forma mejor de hacerlo, ya integrada en el sistema/API.

Si hay una forma mejor de implementar lo anterior, ¿cuál sería?

+0

¿Qué clase usas para "proceso"? java.lang.Process? –

+0

[Process.waitfor()] (http://developer.android.com/reference/java/lang/Process.html#waitFor()) –

Respuesta

3

CountDownLatch sería la mejor solución.

No tengo el ejemplo de detalle, pero creo que puede usarlo con facilidad.

proceso es como a continuación

  1. definen varaiable CountDownLatch llamado pestillo
  2. conjunto de pestillo de recuento de 1
  3. cuando el evento recibido O, hacer una nueva ThreadO. en ThreadO, espere hasta que el conteo del enganche alcance 0.
  4. cuando finaliza el proceso P, bloqueo de cuenta atrás.

Si codifica así, puede manejar muchas situaciones fácilmente.

  1. si O recibido primero, puede esperar hasta que se complete P.
  2. si P recibió primero, puede iniciar O inmediatamente.
  3. puede usar la función de tiempo de espera que proporciona CountDownLatch.

Uso CountDownLatch en la prueba de unidad asyc. Usted puede ver mi código aquí: http://kingori.egloos.com/4554640

A pesar de que no es como su caso, pero se puede agarrar sugerencia de mi código. Además, javadoc de CountDownLatch proporciona un buen ejemplo.

+0

+1 para introducir CountDownLatch. Creo que en realidad podría ir con esta solución en particular. –

3

lo haría de esta manera:

  • en onEventX, comprobar si el proceso de salir, si es así, hacer su acción inmediata (también se puede omitir este paso y simplemente hacer segundo paso)

  • lo contrario, crear AsyncTask donde se llama a Process.waitFor() en doInBackground, cuando se complete, haga su acción en onPostExecute

Con este enfoque, se llama a la acción en la interfaz de usuario t Hread, y tan pronto como sea posible.

No utilice temporizadores para esta tarea. Timer es un método de "votación". Si su temporizador estuviera funcionando demasiado rápido, simplemente perdería tiempo de CPU. Si el tic tac es demasiado lento, su acción se ejecutará con un posible retraso.

+0

+1 para detectar la falacia de un temporizador en este escenario. –

2

Primero, sugiero que si un usuario hace clic en algo, debería ver un resultado inmediato, en su caso, si la acción del botón necesita esperar algo, agregue un círculo que cargue la animación en el botón inmediatamente para indicarle al usuario la acción sucederá en breve.

Ahora para la acción en sí misma, si sólo hay uno (o unos pocos) tales acciones posibles que se producen después de que uno (o unos pocos) posible proceso en segundo plano, que tendría el botón sincrónicamente levantar una bandera (tal vez a través de un miembro de la clase persistente) y tiene el proceso largo sincrónicamente verifique esa bandera una vez que haya finalizado su proceso y realice la acción solicitada al finalizar.

Otra posible opción si el uso de espera y notificar a que el código espere botón para que el proceso finalice, esto se considera generalmente una solución de rendimiento muy alto en Java:

por ejemplo (caso omiso de los errores tipográficos, esto es en -the-residencia):

button.setOnClickListener(new OnClickListener() { 
    public void onClick(View v) { 
     v.post(new Runnable() { 
      @Override 
      public void run() { 
       synchronized (lockObject) { 
        try { 
         lockObject.wait(); 
         doAction(); 
        } catch (InterruptedException e) {} 
       } 
      } 
     } 
    } 
} 

Luego tienen el largo proceso notify cuando termina.

Tenga en cuenta que new Runnable() no crea un nuevo hilo, simplemente se añade una cola de hilo Runnable a la View 's

Como se sugiere por los ratones, el botón onclick debe comprobar si el proceso no se está ejecutando, y si es así solo realiza la acción de inmediato.

De esta manera no es necesario para crear un nuevo hilo (o un AsyncTask que es en realidad un grupo de subprocesos)

+0

+1 para la respuesta detallada y para señalar las dificultades. –

Cuestiones relacionadas