2011-06-16 13 views
78

Estoy intentando algo nuevo en Android para el que necesito acceder al manejador del subproceso de interfaz de usuario.Acceso al manejador de subprocesos de UI desde un servicio

Sé lo siguiente:

  1. El hilo de interfaz de usuario tiene su propio manejador y looper
  2. Cualquier mensaje será puesto en la cola de mensajes del subproceso de interfaz de usuario
  3. El medidor recoge el evento y lo pasó al controlador
  4. El controlador maneja el mensaje y envía el evento specfic a la IU

Quiero tener mi servicio que tiene que obtener el controlador de subprocesos de interfaz de usuario y poner un mensaje en este controlador. Para que este mensaje se procese y se envíe a la interfaz de usuario. Aquí el servicio será un servicio normal que será iniciado por alguna aplicación.

Me gustaría saber si esto es posible. Si es así, sugiérele algunos fragmentos de código para que pueda probarlo.

Regards Girish

Respuesta

27

Crear un objeto Messenger conectado a su Handler y pasar que Messenger a la Service (por ejemplo, en un Intent extra para startService()). El Service puede enviar un Message al Handler a través del Messenger. Here is a sample application demostrando esto.

+0

Gracias por este consejo. Esto fue útil. Consulte el siguiente pila para un flujo de eventos táctiles a mi actividad MyDemo.dispatchTouchEvent (MotionEvent) Línea: 20 PhoneWindow $ DecorView.dispatchTouchEvent (MotionEvent) Línea: 1696 ViewRoot.handleMessage (Mensaje) Línea: 1658 ViewRoot (Handler) .dispatchMessage (Mensaje) línea: 99 Looper.loop() línea: 123 // manejo de eventos comienza aquí ActivityThread.main (String []): la línea 4203 Aquí el ViewRoot es un Handler. Quiero obtener la referencia de este controlador ... ¿es posible obtener esto de mi aplicación? – iLikeAndroid

+0

@iLikeAndroid: si no creó el 'Handler', no puede acceder a él, AFAIK. – CommonsWare

+0

Gracias. Intenté crear una instancia de ViewRoot. Esto no es más que un controlador. Ahora puedo emitir los mensajes en este controlador. El controlador recibe el mensaje. Pero ViewRoot no puede procesar el mensaje, ya que no se inicializa correctamente. Necesito llamar a ViewRoot.setView() para inicializar los datos correctos a ViewRoot. Quiero saber si hay una vista predeterminada o una vista base, etc., que puedo usar para inicializar? – iLikeAndroid

158

este fragmento de código construye una Handler asociado con el principal (UI) hilo:

Handler handler = new Handler(Looper.getMainLooper()); 

A continuación, puede publicar cosas para la ejecución en la principal (UI) de hilo de este modo:

handler.post(runnable_to_call_from_main_thread); 

Si el manejador en sí está creado a partir de la principal (IU) roscar el argumento puede ser omitido por razones de brevedad:

Handler handler = new Handler(); 

El Android Dev Guide en procesos e hilos tiene más información.

+2

¡Lo probó y funciona genial! Un ejemplo de caso de uso: tengo una interfaz web que está siendo servida por un servidor que se ejecuta directamente en el dispositivo. Dado que la interfaz se puede usar para interactuar directamente con la interfaz de usuario, y dado que el servidor necesita ejecutarse en su propio hilo, necesitaba una forma de tocar el hilo de la interfaz de usuario desde fuera de una actividad. El método que describiste funcionó muy bien. – mrPjer

+1

Brillante. Funciona como un encanto, y muy útil. GRACIAS. – JRun

+0

perfecto ^^ simplemente lo usé para actualizar mi interfaz de usuario de StreamingService. exactamente lo que necesitaba gracias! –

4

Por el momento prefiero utilizar la biblioteca de bus de eventos como Otto para este tipo de problema. Sólo suscribir los componentes deseados (actividad):

protected void onResume() { 
    super.onResume(); 
    bus.register(this); 
} 

a continuación, proporcionar un método de devolución de llamada:

public void onTimeLeftEvent(TimeLeftEvent ev) { 
    // process event.. 
} 

y luego, cuando el servicio de ejecutar una sentencia como esta:

bus.post(new TimeLeftEvent(340)); 

Eso POJO se pasar a su actividad anterior y todos los demás componentes de suscripción. Simple y elegante.

2

, usted puede obtener valores a través de receptor de radiodifusión ...... de la siguiente manera, primero debe crear su propio IntentFilter como,

Intent intentFilter=new IntentFilter(); 
intentFilter.addAction("YOUR_INTENT_FILTER"); 

A continuación, cree BroadcastReceiver clase interna como,

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
    /** Receives the broadcast that has been fired */ 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     if(intent.getAction()=="YOUR_INTENT_FILTER"){ 
      //HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW/////////// 
      String receivedValue=intent.getStringExtra("KEY"); 
     } 
    } 
}; 

Ahora Registro su receptor de difusión en onResume() como,

registerReceiver(broadcastReceiver, intentFilter); 

Y finalmente cancelar el registro de BroadcastRec Eiver en OnDestroy() como,

unregisterReceiver(broadcastReceiver); 

Ahora la parte más importante ... tienes que disparar la emisión desde donde se tiene que enviar los valores ..... así como hacer,

Intent i=new Intent(); 
i.setAction("YOUR_INTENT_FILTER"); 
i.putExtra("KEY", "YOUR_VALUE"); 
sendBroadcast(i); 

.... aplausos :)

0

Solución:

  1. Crear una Handler con Looper de Tema principal: requestHa ndler
  2. Crear una Handler con Looper de Tema principal: responseHandler y anular handleMessage método
  3. publicar una tarea Runnable en RequestHandler
  4. Dentro Runnable tarea, llame sendMessage en responseHandler
  5. Este sendMessage resultado invocación de handleMessage en responseHandler.
  6. Obtiene los atributos de la Message y procesarla, actualizar la interfaz de usuario

Código de ejemplo:

/* Handler from UI Thread to send request */ 

    Handler requestHandler = new Handler(Looper.getMainLooper()); 

    /* Handler from UI Thread to process messages */ 

    final Handler responseHandler = new Handler(Looper.getMainLooper()) { 
     @Override 
     public void handleMessage(Message msg) { 

      /* Processing handleMessage */ 

      Toast.makeText(MainActivity.this, 
        "Runnable completed with result:"+(String)msg.obj, 
        Toast.LENGTH_LONG) 
        .show(); 
     } 
    }; 

    for (int i=0; i<10; i++) { 
     Runnable myRunnable = new Runnable() { 
      @Override 
      public void run() { 
       try { 
        /* Send an Event to UI Thread through message. 
         Add business logic and prepare message by 
         replacing example code */ 

        String text = "" + (++rId); 
        Message msg = new Message(); 

        msg.obj = text.toString(); 
        responseHandler.sendMessage(msg); 
        System.out.println(text.toString()); 

       } catch (Exception err) { 
        err.printStackTrace(); 
       } 
      } 
     }; 
     requestHandler.post(myRunnable); 
    } 
Cuestiones relacionadas