2012-06-10 10 views
43

tengo la clase siguiente:¿Cómo recuperar una cadena de AsyncTask?

public class getURLData extends AsyncTask<String, Integer, String>{ 

@Override 
protected String doInBackground(String... params) { 
    String line; 
    try { 
     DefaultHttpClient httpClient = new DefaultHttpClient(); 
     HttpPost httpPost = new HttpPost(params[0]); 

     HttpResponse httpResponse = httpClient.execute(httpPost); 
     HttpEntity httpEntity = httpResponse.getEntity(); 
     line = EntityUtils.toString(httpEntity); 

    } catch (UnsupportedEncodingException e) { 
     line = "<results status=\"error\"><msg>Can't connect to server</msg></results>"; 
    } catch (MalformedURLException e) { 
     line = "<results status=\"error\"><msg>Can't connect to server</msg></results>"; 
    } catch (IOException e) { 
     line = "<results status=\"error\"><msg>Can't connect to server</msg></results>"; 
    } 
    return line; 
} 

@Override 
protected void onPostExecute(String result) { 
    super.onPostExecute(result); 
} 

} 

Y yo estoy tratando de llamarlo así:

String output = null; 
output = new getURLData().execute("http://www.domain.com/call.php?locationSearched=" + locationSearched); 

Pero la variable de salida no está recibiendo datos, en lugar que estoy recibiendo un error:

Type mismatch: cannot convert from AsyncTask<String,Integer,String> to String 
+0

donde recibiste que tienes que hacer 'super.onPostExecute (result);'? ¡No puse esa línea, y todavía funciona! –

Respuesta

101

el método devuelve el executeAynscTask sí, es necesario llamar a get:

output = 
    new getURLData() 
     .execute("http://www.example.com/call.php?locationSearched=" + locationSearched) 
     .get(); 

Esto iniciará un nuevo hilo (a través de execute) mientras que bloquea el flujo actual (a través de get) hasta que el trabajo del nuevo hilo ha sido terminado y el resultado ha sido devuelto.

Si hace esto, se acaba de cumplir su asíncrono tarea en una sincronización uno.

Sin embargo, el problema con el uso de get es que, como bloquea, debe invocarse en una cadena de trabajo. Sin embargo, es necesario llamar al AsyncTask.execute() en el hilo principal. Entonces, aunque este código podría funcionar, puede obtener algunos resultados no deseados. También sospecho que Google ha probado poco el get(), y es posible que hayan introducido un error en algún punto de la línea.

Referencia: AsyncTask.get

+3

Dios mío, esto se vuelve más complicado cuanto más avanzo ... Todo lo que quiero hacer es cuando un usuario hace clic en un botón, carga la pantalla directamente y luego muestra el contenido del http cuando termina. ¿Cómo se hace esto? – Paul

+3

@Paul: Lo que sea que deba hacer después de la ejecución, hágalo en 'onPostExecute'. Es así de simple ... –

+2

Desearía que fuera, pero si me muevo, pasa al método onPostExecute. Ya no tengo las variables params y surgen más problemas al devolver la cadena. Agradezco tu ayuda, pero esto me ha llevado horas, realmente creo que esta es una causa perdida. – Paul

15

prefiero crear el hilo de devolución de llamada bloque de interfaz de usuario. En tu clase, crea un método que se invocará cuando lleguen los datos. Por ejemplo:

private void setData(String data){ 
    mTextView.setText(data); 
} 

Luego, en AsyncTask implemento onPostExecute:

@Override 
protected void onPostExecute(String result) { 
    setData(result); 
} 

Y a continuación, en algún lugar de código sólo tarea de ejecución:

new getURLData().execute(... 

Cuando tarea finalice setData se invoca y mTextView está vacío.

AsyncTask.get() bloqueará su UI, por lo que no hay ninguna razón para usar AsyncTask.

+9

genial, pero ¿cómo puedo llamar 'setData' desde AsyncTask, si ese método está en la otra actividad (la que hace el' .execute')? –

+2

No es así. Simplemente haz lo que necesites en [onPostExecute()] (http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute%28Result%29) – Cyrille

4

Si el usuario hace clic en el botón, entonces tiene que esperar el contenido, ¿qué hacen mientras tanto?

Por qué no hacer esto:

  1. usuario hace clic en el botón.
  2. Usted compruebe la conectividad. Si el usuario no está conectado a Internet, dígaselo.
  3. Usted inicia un IntentService enviando un Intento para enviar la solicitud HTTP.
  4. Cuando la solicitud finaliza, publica una notificación.
  5. El usuario hace clic en la notificación, que regresa a una actividad que puede hacer el siguiente paso.

Esto permite que el usuario se vaya y haga lo que sea mientras se procesa la solicitud.

Un IntentService se ejecuta en segundo plano en su propio hilo. Cuando recibe un Intento, se ejecuta enHandleIntent(). Cuando ese método finaliza, el servicio se almacena en caché: no está activo, pero puede reiniciarse rápidamente cuando llega el siguiente intento.

0

En el siguiente código, obtengo un String (directorName) de AsyncTask.

public class GetDirector { 
    String id; 
    private String baseURL = "http://www.omdbapi.com/?i="; 
    private String finalURL = ""; 
    String theDirector; 

    public GetDirector(String imdbID) throws ExecutionException, InterruptedException { 
     id= imdbID; 
     finalURL = baseURL + id + "&plot=full&r=json"; 
     System.out.println("GetDirector. finalURL= " + finalURL); 
     theDirector = new GetDirectorInfo().execute().get(); 
    } 

    public String getDirector(){ 
     return theDirector; 
    } 

    private class GetDirectorInfo extends AsyncTask<Void, Void,String> { 
     @Override 
     protected String doInBackground(Void... params) { 
      String directorName = null; 

      ServiceHandler sh = new ServiceHandler(); 

      // Making a request to url and getting response 
      String jsonStr = sh.makeServiceCall(finalURL, ServiceHandler.GET); 
      System.out.println("Act_DetailsPage. jsonStr= " + jsonStr); 

      if (jsonStr != null) { 
       try { 
        JSONObject everything = new JSONObject(jsonStr); 

        directorName = everything.getString(JSON_Tags.TAG_DIRECTOR); 
        System.out.println("directorName= "+ directorName); 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       System.out.println("Inside GetDirector. Couldn't get any data from the url"); 
      } 
      return directorName; 
     } 
    } 
} 
+4

Al usar * get * irás síncrono, por lo tanto derrotando el propósito total de AsyncTask que es realizar asincrónicamente. – mradzinski

0

Añadir un parámetro de contexto al constructor de la tarea que se referiría a objetar el lugar donde quiere almacenar datos resultantes.

2
  1. Obtener el contexto en el constructor de esta manera:

    public GetDataTask(Context context) {}

  2. crear una interfaz con el método:

    void onDataRetrieved(String data);

  3. implementar la interfaz en la clase desde donde está creando el objeto Tarea (p. MainActivity)

  4. moldeada el contexto de la interfaz y llamar al método onDataRetrieved

+0

Esto puede causar una pérdida de memoria. Si una operación de larga ejecución tiene acceso al contexto de la actividad, la asynctask evitaría que la actividad se recolecte como basura en caso de cambio de configuración o que el usuario presione la actividad por alguna razón. –

+0

Es necesario utilizar 'WeakReference actWeak = new WeakReference <> (activity)' cuando envía una 'Activity' a' AsyncTask' para evitar pérdidas de memoria y recuperarla con 'Activity act = actWeak.get()' en el método 'doInBackground'. – isabsent

0

Este chiste que funcionó para mí:

String result = MyasyncTask.execute(type, usrPhoneA, usrPWDA).get(); 
+0

¿Cómo puede funcionar esto cuando devuelve una variable AsycTask? –

+0

Devuelve el resultado de la operación en la variable "resultado" después de que PHP procese una función de inicio de sesión. Leí que eso no lo hace una tarea asíncrona, pero en mi caso está bien. – francisqueins

+0

Obtuve una variable asynctask y no fue de mucha utilidad –

0

La única manera de enviar datos desde AsyncTask a IU sin el dolor es Otto o Event autobús. Registre un método que manejará un resultado bajo la anotación @Subscribe en la interfaz de usuario y post a message con un resultado en el método onPostExecute de su AsyncTask.

Cuestiones relacionadas