2010-01-07 16 views
11

Estoy creando una aplicación de Android que tiene que ejecutar solicitudes web en segundo plano y luego manejar los datos recibidos y modificar la interfaz de usuario de acuerdo con la respuesta del servidor.¿Cómo ejecutar la solicitud web en su propio hilo?

El objetivo de publicar solicitudes y gestionar datos en segundo plano es evitar la congelación de la interfaz de usuario. Sin embargo, actualmente noto que la interfaz de usuario se está congelando, así que no estoy seguro de que la lógica funcione como debería.

Aquí es la parte del código que se supone para publicar las solicitudes y manejar las respuestas en su propio hilo y luego pasar los datos a GUI:

public class ServerConnection { 

Queue<String> requests; 

... 

DefaultHttpClient httpClient; 
HttpHost targetHost; 

Handler handler; 

ServerResponseHandler responseHandler; 
Activity activity; 

public ServerConnection(Activity activity){ 
    this.activity = activity; 
    this.responseHandler = (ServerResponseHandler) activity; 
    httpClient = new DefaultHttpClient(); 
    targetHost = new HttpHost(TARGET_DOMAIN, 80, "http"); 
    requests = new LinkedList<String>(); 
} 



private Runnable requestSender = new Runnable(){ 

    @Override 
    public void run() { 
     if(!requests.isEmpty()){ 
      String requestString = requests.remove(); 
      HttpGet httpGet = new HttpGet(requestString); 
      httpGet.addHeader("Accept", "text/xml"); 
      String encodingString = "testuser:testpass"; 
      String sEncodedString = Base64Coder.encodeString(encodingString); 

      try{ 

       String sContent = fetchURL(requestString, sEncodedString); 

       XMLParser xmlParser = new XMLParser(); 

       List <Product> products = xmlParser.getProducts(sContent); 

       responseHandler.onProductsResponse(products); 
      } 
      catch(Exception ex){ 
       Log.e(TAG, ex.getMessage()); 
      } 
     } 
    } 
}; 

public void sendRequest(String requestString){ 
    requests.add(requestString); 
    handler = new Handler(); 
    handler.post(requestSender); 
} 

El método sendRequest() se llama a partir de la actividad principal que implementa ServerResponseHandler. Supongo que la solicitud se ejecuta en su propio hilo y llamando al

responseHandler.onProductsResponse (productos);

la lista de productos (datos de la web) se pasa a la actividad principal. De todos modos, debido al bajo rendimiento, agradecería que alguien pudiera corregir cualquier posible problema en la lógica anterior o sugerir cualquier otra (mejor) opción.

Respuesta

21

Sugiero que eche un vistazo a ASyncTask class (disponible desde Android 1.5).

Simplifica el proceso de creación de un hilo de fondo que se sincroniza con el hilo de la GUI una vez que está completo.

Usted debe ser capaz de lograr lo que está intentando usar código lista de algo tan

private class DownloadFilesTask extends AsyncTask<String, List<Product>, Integer> { 
    protected List<Products> doInBackground(String... requestStrings) { 
     int count = requestStrings.length; 
     int results = 0; 
     for (int i = 0; i < count; i++) { 
      String requestString = requestStrings[i]; 
      HttpGet httpGet = new HttpGet(requestString); 
      httpGet.addHeader("Accept", "text/xml"); 
      String encodingString = "testuser:testpass"; 
      String sEncodedString = Base64Coder.encodeString(encodingString); 
      try{ 
      String sContent = fetchURL(requestString, sEncodedString); 
      XMLParser xmlParser = new XMLParser(); 
      List <Product> products = xmlParser.getProducts(sContent); 
      results++; 
      publishProgress(products); 
      } 
      catch(Exception ex){ 
      Log.e(TAG, ex.getMessage()); 
      } 
     } 
     return results; 
    } 

    protected void onProgressUpdate(Integer... progress) { 
     // TODO You are on the GUI thread, and the first element in 
     // the progress parameter contains the last progress 
     // published from doInBackground, so update your GUI 
    } 

    protected void onPostExecute(int result) { 
     // Processing is complete, result contains the number of 
     // results you processed 
    } 
} 

y ejecutar llamando

new DownloadFilesTask().execute(url1, url2, url3); 
+0

Asynctask o controlador + hilo, depende de usted Niko – tbruyelle

+2

AsyncTask es el camino a seguir. –

+0

Son buenas soluciones – kablu

0

De acuerdo con la handler javadoc, no creo que la post() método crea hilos. Si estoy en lo cierto, ejecute Runnable en el hilo al que está conectado el controlador. Entonces, en este caso, este es el hilo de actividad, ¡así que el hilo de UI! Es por eso que tiene un rendimiento pobre.

Tienes que implementar un Thread que ejecuta tu Runnable. Pero al hacer eso, usted no será capaz de actualizar su actividad como lo hace actualmente llamando:

responseHandler.onProductsResponse(products); 

Esto se debe a que no está más en el hilo de interfaz de usuario, y sólo el hilo de interfaz de usuario está autorizado a interactuar con la UI (así que la actividad). Así que debe reemplazar esta llamada accediendo a su Handler.

Message msg = handler.obtainMessage(); 
Bundle bundle = new Bundle(); 
bundle.putSerializable("products", products); //not sure it will pass here 
msg.setData(bundle); 
handler.sendMessage(msg); 

Y la realización del procedimiento para su handleMessage()Handler:

@Override 
public void handleMessage(Message msg) 
{ 
    List <Product> products = msg.getData().getSerializable("products"); 
    responseHandler.onProductsResponse(products); 
} 

Por último, pero no menos importante: el Handler tiene que ser creada todavía en el hilo de la actividad.

Cuestiones relacionadas