2010-07-20 13 views
37

Tengo una clase común decir, por ejemplo, clase A que se extiende AsyncTask y tiene todos los métodos implementados, es decir, onPreExecute, doinbackground y onPostExecute.Clase común para AsyncTask en Android?

Ahora, hay otras clases que desean usar el objeto Clase A.

Di Clase B utiliza la clase A en la forma que a continuación

A a = new A(context) 
a.execute(url) 

A continuación, voy a buscar el resultado en método get. Pero obtener el método no es la forma correcta de usar AsyncTask. Me gustaría obtener el resultado en onPostExecute. Para eso traté de usar un parámetro booleano que solo se cumplirá en onpostexecute. La clase B verificará hasta que se haga verdadera y cuando se vuelva verdadera obtendrá el resultado.

Pero esto de alguna manera está bloqueando la aplicación.

He colocado el código para asynctask a continuación.

'

import java.io.IOException; 

import org.apache.http.client.ClientProtocolException; 

import org.apache.http.client.HttpClient; 

import org.apache.http.client.ResponseHandler; 

import org.apache.http.client.methods.HttpGet; 

import org.apache.http.impl.client.BasicResponseHandler; 

import org.apache.http.impl.client.DefaultHttpClient; 


import android.app.ProgressDialog; 
import android.content.Context; 
import android.os.AsyncTask; 

public class A extends AsyncTask<String, Void, String> 
{ 
private Context context = null; 

private final HttpClient httpClient = new DefaultHttpClient(); 

private String content = null; 
//private String error = null; 
private String finalResult = null; 
private static boolean isResult = false; 

private ProgressDialog progressDialog = null; 

public BabbleVilleSyncTask(Context context) 
{ 
    this.context = context; 
    progressDialog = new ProgressDialog(this.context); 
} 

protected void onPreExecute() 
{ 
    progressDialog.setMessage("Please Wait...."); 
    progressDialog.show(); 
} 

protected String doInBackground(String... urls) 
{ 
    try 
    { 
     //urls[0] = URLEncoder.encode(urls[0], "UTF-8"); 

     HttpGet httpget = new HttpGet(urls[0]); 
     ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
     content = httpClient.execute(httpget, responseHandler); 
    } 
    /*catch(UnsupportedEncodingException ue) 
    { 
     error = ue.getMessage(); 
    }*/ 
    catch (ClientProtocolException e) 
    { 
     //error = e.getMessage(); 
     cancel(true); 
    } 
    catch (IOException e) 
    { 
     //error = e.getMessage(); 
     cancel(true); 
    } 

    httpClient.getConnectionManager().shutdown(); 

    return content; 
} 

protected void onPostExecute(String result) 
{ 
    finalResult = result; 
    progressDialog.dismiss(); 
    System.out.println("on Post execute called"); 
    isResult = true; 
} 

public boolean getIsResult() 
{ 
    return isResult; 
} 

public void setIsResult(boolean flag) 
{ 
    isResult = flag; 
} 

public String getResult() 
{ 
    return finalResult; 
} 
} 

'

Puede alguien que me haga saber lo que puede ser el problema?

Saludos

Sunil

Respuesta

128

Una manera limpia de utilizar AsyncTask para obtener un resultado sería utilizar una interfaz de devolución de llamada.

Aquí es un simple ejemplo de este concepto:

interface AsyncTaskCompleteListener<T> { 
    public void onTaskComplete(T result); 
} 

entonces en su clase B:

class B implements AsyncTaskCompleteListener<String> { 

    public void onTaskComplete(String result) { 
     // do whatever you need 
    } 

    public void launchTask(String url) { 
     A a = new A(context, this); 
     a.execute(url); 
    } 
} 

ahora debería añadir el siguiente código a su Una clase:

class A extends AsyncTask<String, Void, String> { 
    private AsyncTaskCompleteListener<String> callback; 

    public A(Context context, AsyncTaskCompleteListener<String> cb) { 
     this.context = context; 
     this.callback = cb; 
    } 

    protected void onPostExecute(String result) { 
     finalResult = result; 
     progressDialog.dismiss(); 
     System.out.println("on Post execute called"); 
     callback.onTaskComplete(result); 
    } 
} 

De esta manera, no necesita esperar explícitamente para que su tarea complete, en cambio, su código principal (que probablemente sea th El subproceso de IU principal), está esperando en el ciclo de eventos android normal, y se llamará automáticamente al método onTaskComplete, lo que permite manejar el resultado de la tarea allí.

+0

Muchas gracias por esto. Pero, ¿qué sucede si quiero llamar a 3 URL en un método de ejecución? Entonces, ¿cómo podemos buscar la respuesta? Cualquier idea – sunil

+1

Tiene un método onProgressMethod que debería hacer bien el trabajo, si llama a publishProgress desde su tarea para cada url. – SirDarius

+0

¿Podría elaborar un poco más? Actualmente estoy intentando convertir este método: public static invokeWebServiceRequest (String uri, String username, String password, String targetKey); dentro de una clase que amplía AsyncTask. ¿cómo pasaría esos parámetros (de mi método anterior) a doInBackground (Params ...)? gracias! – Cole

1

que haría que la clase A una clase privada incrustada en la clase padre, y una vez que se ha hecho con el trabajo que se debe actualizar las propiedades de la clase padre, eso es posible onPostExecute.

+0

Sí, esto es posible. Pero tengo 15-20 actividades y cada una tiene conexión http. Entonces, esta es la razón por la que creé una clase separada para eso. Pero ahora estoy enfrentando el problema. Entonces, ¿hay alguna forma de obtener el resultado de onPostExecute en otra clase? – sunil

+0

Si tiene más de 15 actividades usando una conexión http, necesita subclasificarlas de modo tal que la misma funcionalidad se defina en solo 1 superclase de la que herede. – Pentium10

+0

por favor continúe, ya que estoy tratando de crear una clase/singleton para todas mis solicitudes http, que no interrumpen el hilo principal/UI. – Cole

4
public abstract class BaseTask<T> extends AsyncTask<Object, Void, T> { 

    public Context context; 
    public ProgressDialog dialog; 
    public Exception exception; 

    protected BaseTask() { 
    } 

    public BaseTask(Context context) { 
     this.context = context; 
     this.dialog = new ProgressDialog(context); 
    } 

    @Override 
    protected void onPreExecute() { 
     this.dialog.setMessage(context.getResources().getString(R.string.loading)); 
     this.dialog.show(); 
    } 

    @Override 
    protected T doInBackground(Object... objects) { 
     try { 
      return doWork(objects); 
     } catch (Exception e) { 
      exception = e; 
     } 
     return null; 
    } 

    @Override 
    protected void onPostExecute(T result) { 
     if (dialog.isShowing()) dialog.dismiss(); 
     if (exception == null) { 
      onResult(result); 
     } else { 
      onError(); 
     } 
    } 



    public abstract T doWork(Object... objects) throws Exception; 
    public abstract void onResult(T result); 
    public abstract void onError(); 



} 
Cuestiones relacionadas