wake-up-neo.com

Wie bekomme ich einen String von AsyncTask zurück?

Ich habe folgende Klasse:

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

}

Und ich versuche es so zu nennen:

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

Die Ausgabevariable erhält jedoch keine Daten, stattdessen wird ein Fehler angezeigt:

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

Die Methode execute gibt die AynscTask selbst zurück, Sie müssen get aufrufen:

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

Dadurch wird ein neuer Thread (über execute) gestartet, während der aktuelle Thread (über get) blockiert wird, bis die Arbeit aus dem neuen Thread abgeschlossen und das Ergebnis zurückgegeben wurde. 

Wenn Sie dies tun, haben Sie Ihre async - Aufgabe in eine sync - Aufgabe umgewandelt.

Das Problem bei der Verwendung von get besteht jedoch darin, dass es aufgrund der Blockierung für einen Arbeitsthread aufgerufen werden muss. AsyncTask.execute() muss jedoch im Hauptthread aufgerufen werden. Obwohl dieser Code funktionieren könnte, können Sie einige unerwünschte Ergebnisse erhalten. Ich habe auch den Verdacht, dass get() von Google zu wenig getestet wird, und es ist möglich, dass ein Fehler irgendwo auf der ganzen Linie aufgetreten ist.

Referenz: AsyncTask.get

107
K-ballo

Ich würde eher einen Callback als einen Block für den UI-Thread erstellen. Zum Beispiel:

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

Implementieren Sie dann in AsyncTask onPostExecute:

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

Und dann irgendwo im Code einfach die Aufgabe ausführen:

new getURLData().execute(...

Wenn der Task abgeschlossen ist, wird setData aufgerufen und mTextView gefüllt.

AsyncTask.get () blockiert Ihre Benutzeroberfläche, sodass es keinen Grund gibt, AsyncTask zu verwenden.

18
pawelzieba

Wenn der Benutzer auf die Schaltfläche klickt, muss er auf den Inhalt warten, was machen sie inzwischen?

Warum machst du das nicht:

  1. Benutzer klickt auf die Schaltfläche.
  2. Sie auf Konnektivität prüfen. Wenn der Benutzer nicht mit dem Internet verbunden ist, informieren Sie ihn.
  3. Sie starten einen IntentService, indem Sie eine Absicht senden, um die HTTP-Anforderung zu senden.
  4. Wenn die Anforderung abgeschlossen ist, veröffentlichen Sie eine Benachrichtigung.
  5. Der Benutzer klickt auf die Benachrichtigung, die zu einer Aktivität zurückkehrt, die den nächsten Schritt ausführen kann.

Auf diese Weise kann der Benutzer loslegen und tun, was während der Bearbeitung der Anforderung geschieht.

Ein IntentService wird im Hintergrund in einem eigenen Thread ausgeführt. Wenn ein Intent empfangen wird, wird onHandleIntent () ausgeführt. Wenn diese Methode abgeschlossen ist, wird der Dienst zwischengespeichert: Er ist nicht aktiv, kann jedoch bei Ankunft des nächsten Intents schnell wieder gestartet werden.

4
Joe Malin
  1. Holen Sie sich den Kontext im Konstruktor wie folgt:

    public GetDataTask(Context context) {}

  2. Erstellen Sie ein Interface mit der Methode:

    void onDataRetrieved(String data);

  3. Implementieren Sie die Schnittstelle in der Klasse, von der aus Sie das Task-Objekt erstellen (z. B. MainActivity).

  4. Umwandeln Sie den Kontext in die Schnittstelle, und rufen Sie die onDataRetrieved-Methode auf

2

Die einzige Möglichkeit, Daten von AsyncTask an die Benutzeroberfläche schmerzfrei zu senden, ist Otto oder Event Bus. Registrieren Sie eine Methode, die ein Ergebnis unter @Subscribe-Anmerkung in der Benutzeroberfläche behandelt, und post eine message mit einem Ergebnis in onPostExecute-Methode Ihrer AsyncTask.

0
isabsent

Dieser EIN LINER hat für mich gearbeitet:

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

Fügen Sie dem Konstruktor der Aufgabe einen Kontextparameter hinzu, der auf das Objekt verweist, in dem Sie die resultierenden Daten speichern.

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

Im folgenden Code bekomme ich einen String (directorName) von AsyncTask zurück. 

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