web-dev-qa-db-fra.com

Comment obtenir une chaîne en retour d'AsyncTask?

J'ai la classe suivante:

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);
}

}

Et j'essaye d'appeler ça comme ça:

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

Mais la variable de sortie ne reçoit pas de données, je reçois une erreur:

Type mismatch: cannot convert from AsyncTask<String,Integer,String> to String
49
Paul

La méthode execute renvoie la AynscTask elle-même, vous devez appeler get:

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

Cela démarrera un nouveau thread (via execute) tout en bloquant le thread actuel (via get) jusqu'à ce que le travail du nouveau thread soit terminé et que le résultat soit renvoyé. 

Si vous faites cela, vous venez de transformer votre tâche async en une tâche sync.

Cependant, le problème lié à l'utilisation de get est que, parce qu'il bloque, il doit être appelé sur un thread de travail. Cependant, AsyncTask.execute() doit être appelé sur le thread principal. Ainsi, bien que ce code puisse fonctionner, vous pouvez obtenir des résultats indésirables. Je soupçonne également que get() est sous-testé par Google, et il est possible qu’ils aient introduit un bogue quelque part dans la suite.

Référence: AsyncTask.get

107
K-ballo

Je préférerais créer un rappel que de bloquer le thread UI . Dans votre classe, créez une méthode qui sera invoquée à l'arrivée des données. Par exemple:

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

Ensuite, dans AsyncTask, implémentez onPostExecute:

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

Et puis quelque part dans le code, exécutez simplement la tâche:

new getURLData().execute(...

Lorsque la tâche est terminée, setData est appelée et mTextView est rempli.

AsyncTask.get () blok votre interface utilisateur, il n'y a donc aucune raison d'utiliser AsyncTask.

18
pawelzieba

Si l'utilisateur clique sur le bouton, il doit attendre le contenu, que fait-il pendant ce temps?

Pourquoi ne pas faire ceci:

  1. L'utilisateur clique sur le bouton.
  2. Vous vérifiez la connectivité . Si l'utilisateur n'est pas connecté à Internet, dites-le-lui.
  3. Vous démarrez IntentService en envoyant une intention d'envoi de la requête HTTP.
  4. Lorsque la demande est terminée, vous publiez une notification.
  5. L'utilisateur clique sur la notification qui renvoie à une activité pouvant effectuer l'étape suivante.

Cela permet à l'utilisateur de faire n'importe quoi pendant le traitement de la demande.

Un IntentService s'exécute en arrière-plan sur son propre thread. Lorsqu'il reçoit une intention, il s'exécute surHandleIntent (). Lorsque cette méthode est terminée, le service est mis en cache: il n'est pas actif, mais il peut redémarrer rapidement lorsque le prochain Intent arrive.

4
Joe Malin

Le seul moyen d'envoyer des données de AsyncTask à l'interface utilisateur sans douleur est Otto ou Event bus. Enregistrez une méthode qui gérera un résultat sous l'annotation @Subscribe dans l'interface utilisateur et post une message avec un résultat correspondant dans la méthode onPostExecute de votre AsyncTask.

0
isabsent

Ce ONE LINER a fonctionné pour moi:

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

Ajoutez un paramètre de contexte au constructeur de la tâche qui ferait référence à l'objet sur lequel vous souhaitez stocker les données résultantes.

class PopulateArray extends AsyncTask<Integer, Integer, ArrayList<String>>
{
    Context _context; // context may be what ever activity or object you want to store result in
    PopulateArray(Context context)
    {
        _context = context;
    }
    @Override
    protected ArrayList<String> doInBackground(Integer... integers)
    {
        ArrayList<String> data = new ArrayList<String>();
        //manipulate
        return data;
    }

    @Override
    protected void onPostExecute(ArrayList<String> strings)
    {
        _context.setData(strings);
    }
}
0
Dragas

Dans le code suivant, je récupère une chaîne (directorName) auprès 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;
        }
    }
}
0
Gene