2011-06-08 11 views
9

Creé una clase que ampliaba el Subproceso para recuperar la ubicación del usuario a través de LocationManager en un subproceso que no es de la interfaz de usuario. Implementé esto como un hilo porque se debe iniciar a pedido y hacer su trabajo solo por un tiempo limitado. Por cierto, tuve que agregar un objeto Looper en el hilo, para poder crear el controlador para el LocationManager (onLocationChanged).Cómo administrar Loopers y Subprocesos (¡el hilo ya no se muere!)

Este es el código:

public class UserLocationThread extends Thread implements LocationListener { 
//... 
public void run() { 
    try { 
     Looper.prepare(); 
     locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); 
     Looper.loop(); 
     Looper.myLooper().quit(); 
    } catch (Exception e) { 
     //... 
    } 
} 

@Override 
public void onLocationChanged(Location location) { 
    locationManager.removeUpdates(this); 
    //... 
    handler.sendMessage(msg); //this is the handler for communication with father thread 
} 

//...} 

Me gustaría que el hilo para iniciar, recibir los datos de localización del usuario (en este caso sólo una vez), envía los datos al hilo principal a través de un mensaje a la controlador, y luego muere. El problema es que en mi caso el hilo ya no muere, una vez que finaliza el método de ejecución (eso debería estar bien, porque de lo contrario onLocationChanged no recibiría las nuevas ubicaciones).

Pero de esta manera, suponiendo que los métodos stop y suspender de la hebra están en desuso, ¿cuál sería una buena forma, en este caso al menos, para hacer que un hilo con un looper muera?

Gracias de antemano;)

Respuesta

20

Puede salir explícitamente de Looper 's bucle que utiliza Handler:

private Handler mUserLocationHandler = null; 
private Handler handler = null; 

public class UserLocationThread extends Thread implements LocationListener {  

public void run() { 
    try { 
      Looper.prepare(); 
     mUserLocationHandler = new Handler(); 
     locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); 
     Looper.loop(); 

    } catch (Exception e) { 
     //... 
    } 
} 


@Override 
public void onLocationChanged(Location location) { 
    locationManager.removeUpdates(this); 
    //... 
    handler.sendMessage(msg); 
    if(mUserLocationHandler != null){ 
     mUserLocationHandler.getLooper().quit(); 
    } 
} 
+0

En mi caso, "manejador" es un objeto Handler pasado a este hilo desde el hilo de llamada, para ser utilizado para pasar los datos recopilados de uno a otro. Por lo tanto, no puedo llamar a handler.getLooper(). Quit() porque se refiere al hilo de actividad, y no al userLocationThread. Tenga en cuenta que onLocationChanged está dentro del nuevo hilo, y que Looper debe permitir que se llame a este método de devolución de llamada cuando el locationManager recibe una ubicación. –

+0

He actualizado la respuesta para reflejar su caso. – inazaruk

+0

Gracias; eso hace el trabajo. Por cierto, ¿cuál es la diferencia entre handler.getLooper(). Quit() y Looper.myLooper(). Quit()? ¡Pensé que funcionan igual! –

-1

extender la clase AsyncTask. Hace todo el enhebrado y manejo para usted automáticamente.

+1

No creo que 'AsyncTask' funcione en este caso ya que el hilo tiene que tener el bucle' Looper'. – inazaruk

0

'Me implementado esto como una banda de rodadura, ya que tiene que ser iniciado a solicitud y haga su trabajo sólo por un tiempo limitado.'

Esto suena como una razón perfecta para simplemente reutilizar el looper principal. No es necesario generar un nuevo hilo aquí. Si está haciendo un trabajo de bloqueo (E/S de red, etc.) en onLocationChanged(), en ese punto podría girar una ASyncTask.

Implementa LocationListener en tu actividad/servicio o lo que sea y deja que use el looper principal de forma predeterminada.

No es necesario engendrar un nuevo hilo, ponerlo en un bucle y luego salir de inmediato.

0

IntentService es bueno para hacer este trabajo.

IntentService es una clase base para los servicios que manejan solicitudes asíncronas (expresadas como Intents) bajo demanda. Los clientes envían solicitudes a través de llamadas startService (Intent); el servicio se inicia según sea necesario, maneja cada intención a su vez utilizando un hilo de trabajo, y se detiene cuando se queda sin trabajo.

0

Looper().quit(); es bueno, y según la especificación:

hace que el método de bucle() para terminar sin procesar más mensajes en la cola de mensajes.

Pero, si usted tiene una tarea que ya está en proceso, y desea detener también, se puede adquirir el hilo de trabajo y hacer que se interrumpa:

@Override 
public void onLocationChanged(Location location) { 
    locationManager.removeUpdates(this); 
    handler.sendMessage(msg); //this is the handler for communication with father thread 
    if(mUserLocationHandler != null){ 
     mUserLocationHandler.getLooper().quit(); 
     mUserLocationHandler.getLooper().getThread().interrupt(); // <-- here 
    } 

}

Esto funciona bien con la mayoría de IO, y bloqueo/espera de hilo.

Cuestiones relacionadas