379 Stimmen

Wie bekommt man das Ergebnis von OnPostExecute() zur Hauptaktivität, weil AsyncTask eine separate Klasse ist?

Ich habe diese zwei Klassen. Meine Hauptaktivität und diejenige, die die AsyncTask In meiner Hauptaktivität muss ich nun das Ergebnis aus der OnPostExecute() en el AsyncTask . Wie kann ich meine Haupttätigkeit bestehen oder das Ergebnis erhalten?

Hier sind die Beispielcodes.

Meine Haupttätigkeit.

public class MainActivity extends Activity{

    AasyncTask asyncTask = new AasyncTask();

    @Override
    public void onCreate(Bundle aBundle) {
        super.onCreate(aBundle);            

        //Calling the AsyncTask class to start to execute.  
        asyncTask.execute(a.targetServer); 

        //Creating a TextView.
        TextView displayUI = asyncTask.dataDisplay;
        displayUI = new TextView(this);
        this.setContentView(tTextView); 
    }

}

Dies ist die AsyncTask-Klasse

public class AasyncTask extends AsyncTask<String, Void, String> {

TextView dataDisplay; //store the data  
String soapAction = "http://sample.com"; //SOAPAction header line. 
String targetServer = "https://sampletargeturl.com"; //Target Server.

//SOAP Request.
String soapRequest = "<sample XML request>";    

@Override
protected String doInBackground(String... string) {

String responseStorage = null; //storage of the response

try {

    //Uses URL and HttpURLConnection for server connection. 
    URL targetURL = new URL(targetServer);
    HttpURLConnection httpCon = (HttpURLConnection) targetURL.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setDoInput(true);
    httpCon.setUseCaches(false); 
    httpCon.setChunkedStreamingMode(0);

    //properties of SOAPAction header
    httpCon.addRequestProperty("SOAPAction", soapAction);
    httpCon.addRequestProperty("Content-Type", "text/xml; charset=utf-8"); 
    httpCon.addRequestProperty("Content-Length", "" + soapRequest.length());
    httpCon.setRequestMethod(HttpPost.METHOD_NAME);

    //sending request to the server.
    OutputStream outputStream = httpCon.getOutputStream(); 
    Writer writer = new OutputStreamWriter(outputStream);
    writer.write(soapRequest);
    writer.flush();
    writer.close();

    //getting the response from the server
    InputStream inputStream = httpCon.getInputStream(); 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);

    int intResponse = httpCon.getResponseCode();

    while ((intResponse = bufferedReader.read()) != -1) {
        byteArrayBuffer.append(intResponse);
    }

    responseStorage = new String(byteArrayBuffer.toByteArray()); 

    } catch (Exception aException) {
    responseStorage = aException.getMessage(); 
    }
    return responseStorage;
}

protected void onPostExecute(String result) {

    aTextView.setText(result);

}       

}

779voto

HelmiB Punkte 12185

Einfach:

  1. erstellen. interface Klasse, wobei String output ist optional oder kann jede beliebige Variable sein, die Sie zurückgeben möchten.

     public interface AsyncResponse {
         void processFinish(String output);
     }
  2. Gehen Sie zu Ihrem AsyncTask Klasse, und deklarieren Sie die Schnittstelle AsyncResponse als ein Feld:

     public class MyAsyncTask extends AsyncTask<Void, Void, String> {
       public AsyncResponse delegate = null;
    
         @Override
         protected void onPostExecute(String result) {
           delegate.processFinish(result);
         }
      }
  3. In Ihrer Hauptaktivität müssen Sie implements Schnittstelle AsyncResponse .

     public class MainActivity implements AsyncResponse{
       MyAsyncTask asyncTask =new MyAsyncTask();
    
       @Override
       public void onCreate(Bundle savedInstanceState) {
    
          //this to set delegate/listener back to this class
          asyncTask.delegate = this;
    
          //execute the async task 
          asyncTask.execute();
       }
    
       //this override the implemented method from asyncTask
       @Override
       void processFinish(String output){
          //Here you will receive the result fired from async class 
          //of onPostExecute(result) method.
        }
      }

アップデイト

Ich wusste nicht, dass dies für viele von euch so ein Favorit ist. Hier ist also die einfache und bequeme Art der Verwendung interface .

immer noch dasselbe verwenden interface . Zu Ihrer Information: Sie können dies kombinieren zu AsyncTask Klasse.

in AsyncTask Klasse :

public class MyAsyncTask extends AsyncTask<Void, Void, String> {

  // you may separate this or combined to caller class.
  public interface AsyncResponse {
        void processFinish(String output);
  }

  public AsyncResponse delegate = null;

    public MyAsyncTask(AsyncResponse delegate){
        this.delegate = delegate;
    }

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

tun Sie dies in Ihrem Activity Klasse

public class MainActivity extends Activity {

   MyAsyncTask asyncTask = new MyAsyncTask(new AsyncResponse(){

     @Override
     void processFinish(String output){
     //Here you will receive the result fired from async class 
     //of onPostExecute(result) method.
     }
  }).execute();

 }

Oder Sie implementieren die Schnittstelle erneut in der Aktivität

public class MainActivity extends Activity 
    implements AsyncResponse{

    @Override
    public void onCreate(Bundle savedInstanceState) {

        //execute the async task 
        new MyAsyncTask(this).execute();
    }

    //this override the implemented method from AsyncResponse
    @Override
    void processFinish(String output){
        //Here you will receive the result fired from async class 
        //of onPostExecute(result) method.
    }
}

Wie Sie sehen können 2 Lösungen oben, die erste und dritte, muss es Methode erstellen processFinish Im anderen Fall befindet sich die Methode im Parameter des Aufrufers. Die dritte ist sauberer, weil es keine verschachtelte anonyme Klasse gibt.

Tipp : Ändern Sie String output , String response y String result auf verschiedene übereinstimmende Typen, um verschiedene Objekte zu erhalten.

25voto

quietmint Punkte 13182

Es gibt mehrere Möglichkeiten:

  • Nest der AsyncTask Klasse innerhalb Ihrer Activity Klasse. Vorausgesetzt, Sie verwenden nicht dieselbe Aufgabe in mehreren Aktivitäten, ist dies der einfachste Weg. Ihr gesamter Code bleibt gleich, Sie verschieben nur die bestehende Aufgabenklasse als verschachtelte Klasse innerhalb der Klasse Ihrer Aktivität.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
  • Erstellen Sie einen eigenen Konstruktor für Ihre AsyncTask die einen Verweis auf Ihre Activity . Sie würden die Aufgabe instanziieren mit etwas wie new MyAsyncTask(this).execute(param1, param2) .

    public class MyAsyncTask extends AsyncTask<String, Void, String> {
        private Activity activity;
    
        public MyAsyncTask(Activity activity) {
            this.activity = activity;
        }
    
        // existing AsyncTask code
        ...
    }

19voto

Nicu P Punkte 243

Sie können diesen Code in Ihrer Klasse Main ausprobieren. Das hat bei mir funktioniert, aber ich habe Methoden auf andere Weise implementiert

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}

19voto

Arshad Punkte 945

Meiner Meinung nach ist der folgende Ansatz sehr einfach.

Ich habe eine Schnittstelle für Callback deklariert

public interface AsyncResponse {
    void processFinish(Object output);
}

Dann wird ein asynchroner Task zur Beantwortung aller Arten von parallelen Anfragen erstellt

 public class MyAsyncTask extends AsyncTask<Object, Object, Object> {

    public AsyncResponse delegate = null;//Call back interface

    public MyAsyncTask(AsyncResponse asyncResponse) {
        delegate = asyncResponse;//Assigning call back interfacethrough constructor
    }

    @Override
    protected Object doInBackground(Object... params) {

      //My Background tasks are written here

      return {resutl Object}

    }

    @Override
    protected void onPostExecute(Object result) {
        delegate.processFinish(result);
    }

}

Dann wird die asynchrone Aufgabe beim Klicken auf eine Schaltfläche in der Aktivität Klasse aufgerufen.

public class MainActivity extends Activity{

    @Override
    public void onCreate(Bundle savedInstanceState) {

    Button mbtnPress = (Button) findViewById(R.id.btnPress);

    mbtnPress.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {

                    @Override
                    public void processFinish(Object output) {
                        Log.d("Response From Asynchronous task:", (String) output);

                        mbtnPress.setText((String) output);
                   }
                });

                asyncTask.execute(new Object[] { "Your request to aynchronous task class is giving here.." });

            }
        });

    }

}

Gracias

17voto

Rahul Punkte 10167

Diese Antwort kommt vielleicht etwas spät, aber ich möchte ein paar Dinge erwähnen, wenn Ihr Activity abhängig von AsyncTask . Das würde Ihnen helfen, Abstürze und Speicherverwaltung zu vermeiden. Wie bereits in den obigen Antworten erwähnt, verwenden Sie interface nennen wir sie auch Rückrufe. Sie werden als Informanten arbeiten, aber niemals senden stark Hinweis auf Activity ou interface immer verwenden schwach Referenz in diesen Fällen.

Wie das zu Problemen führen kann, sehen Sie in der folgenden Bildschirmabbildung.

enter image description here

Wie Sie sehen können, wenn wir beginnen AsyncTask avec un stark Referenz, dann gibt es keine Garantie, dass unsere Activity / Fragment am Leben bleiben, bis wir Daten erhalten, daher wäre es besser, wenn wir WeakReference in diesen Fällen und das wird auch bei der Speicherverwaltung helfen, da wir nie die starke Referenz unserer Activity dann kommt es nach seiner Verzerrung für die Müllabfuhr in Frage.

Im folgenden Codeschnipsel finden Sie heraus, wie Sie WeakReference verwenden können -

MyTaskInformer.java Schnittstelle, die als Informant fungiert.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.java AsyncTask, um lang laufende Aufgaben zu erledigen, die WeakReference .

public class MySmallAsyncTask extends AsyncTask<String, Void, String> {

    // ***** Hold weak reference *****
    private WeakReference<MyTaskInformer> mCallBack;

    public MySmallAsyncTask(MyTaskInformer callback) {
        this.mCallBack = new WeakReference<>(callback);
    }

    @Override
    protected String doInBackground(String... params) {

        // Here do whatever your task is like reading/writing file
        // or read data from your server or any other heavy task

        // Let us suppose here you get response, just return it
        final String output = "Any out, mine is just demo output";

        // Return it from here to post execute
        return output;
    }

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

        // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask

        // Make sure your caller is active

        final MyTaskInformer callBack = mCallBack.get();

        if(callBack != null) {
            callBack.onTaskDone(s);
        }
    }
}

MainActivity.java Diese Klasse wird verwendet, um meine AsyncTask implementieren interface zu dieser Klasse und override diese obligatorische Methode.

public class MainActivity extends Activity implements MyTaskInformer {

    private TextView mMyTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMyTextView = (TextView) findViewById(R.id.tv_text_view);

        // Start your AsyncTask and pass reference of MyTaskInformer in constructor
        new MySmallAsyncTask(this).execute();
    }

    @Override
    public void onTaskDone(String output) {

        // Here you will receive output only if your Activity is alive.
        // no need to add checks like if(!isFinishing())

        mMyTextView.setText(output);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X