Jak uzyskać wynik OnPostExecute () do głównej aktywności, ponieważ AsyncTask jest oddzielną klasą?

Mam dwie klasy. Moja główna aktywność i ta, która rozszerza AsyncTask, Teraz w mojej głównej aktywności muszę uzyskać wynik z OnPostExecute() w AsyncTask. Jak mogę przejść lub uzyskać wynik do mojej głównej aktywności?

Oto przykładowe kody. Moja główna działalność.
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); 
    }

}

To jest klasa AsyncTask

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

}       

}   
Author: God, 2012-09-25

14 answers

Łatwe:

  1. Utwórz klasę interface, Gdzie String output jest opcjonalne lub może być dowolną zmienną, którą chcesz zwrócić.

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
  2. Przejdź do klasy AsyncTask i zadeklaruj interfejs AsyncResponse jako pole:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
  3. W swojej głównej aktywności musisz implements Interfejs 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.
       }
     }
    

UPDATE

Nie wiedziałem, że to takie ulubione dla wielu z was. Oto prosty i wygodny sposób użycia interface.

Nadal używam tego samego interface. Dla twojej wiadomości, możesz połączyć to w AsyncTask klasę.

W klasie AsyncTask:

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

Zrób to w swojej klasie Activity

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

 }

Lub, zaimplementowanie interfejsu na aktywności ponownie

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.
    }
}

Jak widać powyżej 2 rozwiązania, pierwsze i trzecie, należy utworzyć metodę processFinish, drugie, metoda znajduje się wewnątrz parametru wywołującego. Trzeci jest bardziej schludny, ponieważ nie ma zagnieżdżonej anonimowej klasy. Hope this pomaga

Wskazówka : Zmień String output, String response, i String result do różnych typów dopasowania w celu uzyskania różnych obiektów.

 647
Author: HelmiB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-22 12:05:51

Istnieje kilka opcji:

  • Zagnieźdź klasę AsyncTask w swojej klasie Activity. Zakładając, że nie używasz tego samego zadania w wielu działaniach, jest to najprostszy sposób. Cały Twój kod pozostaje taki sam, po prostu przenosisz istniejącą klasę zadania, aby stała się klasą zagnieżdżoną wewnątrz klasy Twojej aktywności.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
    
  • Utwórz niestandardowy konstruktor dla twojego AsyncTask, który ma odniesienie do twojego Activity. Utworzyłbyś zadanie czymś takim jak 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
        ...
    }
    
 22
Author: user113215,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-24 02:29:05

Czułem, że poniższe podejście jest bardzo łatwe.

I have declared an interface for callback

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

Następnie utworzono zadanie asynchroniczne do odpowiadania na wszystkie typy równoległych żądań

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

}

Następnie wywołane zadanie asynchroniczne po kliknięciu przycisku w klasie activity.

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


            }
        });

    }



}

Dzięki

 14
Author: Arshad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-23 21:23:19

Możesz wypróbować ten kod w swojej klasie głównej. To działało dla mnie, ale zaimplementowałem metody w inny sposób

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}
 13
Author: Nicu P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-27 14:23:41

Możesz to zrobić w kilku wierszach, po prostu nadpisuj onPostExecute podczas wywoływania AsyncTask. Oto przykład dla ciebie:

new AasyncTask()
{
    @Override public void onPostExecute(String result)
    {
       // do whatever you want with result 
    }
}.execute(a.targetServer);

Mam nadzieję, że ci pomogło, miłego rozpieszczania :)

 6
Author: Sa Qada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-17 16:00:41

In your Oncreate ():

`

myTask.execute("url");
String result = "";
try {
      result = myTask.get().toString();
} catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
}catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();

}`

 5
Author: user3691697,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-30 14:43:46

Dlaczego ludzie tak to utrudniają?

To powinno wystarczyć.

Nie implementuj onPostExecute na zadaniu asynchronicznym, raczej zaimplementuj go na aktywności:

public class MainActivity extends Activity 
{

@Override
public void onCreate(Bundle savedInstanceState) {

    //execute the async task 
    MyAsyncTask task = new MyAsyncTask(){
            protected void onPostExecute(String result) {
                //Do your thing
            }       

    }

    task.execute("Param");

}


}
 4
Author: bugdayci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-26 19:12:04

Ta odpowiedź może się spóźnić, ale chciałbym wspomnieć o kilku rzeczach, gdy Activity zależy od AsyncTask. To pomoże Ci w zapobieganiu awariom i zarządzaniu pamięcią. Jak już wspomniano w powyższych odpowiedzi iść z interface, mówimy również ich wywołań zwrotnych. Będą pracować jako informator, ale nigdy przenigdy nie wysyłają silnego odniesienia Activity lub interface Zawsze używaj słabego odniesienia w tych przypadkach.

Zapoznaj się z poniższym zrzutem ekranu, aby dowiedzieć się, jak może to spowodować problemy.

Tutaj wpisz opis obrazka

Jak widać, jeśli zaczęliśmy AsyncTask od silnego odniesienia to nie ma gwarancji, że nasz Activity/Fragment będzie żył dopóki nie uzyskamy danych, więc lepiej byłoby użyć WeakReference w takich przypadkach, a to również pomoże w zarządzaniu pamięcią, ponieważ nigdy nie będziemy trzymać silnej referencji naszego Activity, wtedy będzie on kwalifikował się do zbierania śmieci po jego zniekształceniu.

Sprawdź poniższy fragment kodu, aby dowiedzieć się, jak używać awesome WeakReference -

MyTaskInformer.java interfejs, który będzie działał jako informator.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.java AsyncTask do wykonania długiego zadania, które użyje 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 ta klasa jest używana do rozpoczęcia mojej AsyncTask implementacji interface na tej klasie i {[19] } tej obowiązkowej metody.

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);
    }
}
 4
Author: Rahul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-04 07:36:35

Można nazwać get() metoda AsyncTask (lub przeciążenie get(long, TimeUnit)). Ta metoda zostanie zablokowana, dopóki AsyncTask nie zakończy swojej pracy, w którym to momencie zwróci ci Result.

Mądrze byłoby wykonać inną pracę między utworzeniem / rozpoczęciem zadania asynchronicznego a wywołaniem metody get, w przeciwnym razie nie wykorzystasz zadania asynchronicznego bardzo efektywnie.

 4
Author: nicholas.hauschild,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 13:11:21

Witam mozna zrobic cos takiego:

  1. Tworzenie klasy implementującej AsyncTask

    // TASK 
    public class SomeClass extends AsyncTask<Void, Void, String>>
    {
    
        private OnTaskExecutionFinished _task_finished_event;
    
        public interface OnTaskExecutionFinished
        {
            public void OnTaskFihishedEvent(String Reslut);
        }
    
        public void setOnTaskFinishedEvent(OnTaskExecutionFinished _event)
        {
            if(_event != null)
            {
                this._task_finished_event = _event;
            }
        }
    
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
    
        }
    
        @Override
        protected String doInBackground(Void... params)
        {
            // do your background task here ...
    
            return "Done!";
        }
    
        @Override
        protected void onPostExecute(String result)
        {
            super.onPostExecute(result);
            if(this._task_finished_event != null)
            {
                this._task_finished_event.OnTaskFihishedEvent(result);
            }
            else
            {
                Log.d("SomeClass", "task_finished even is null");
            }
        }
    }
    
  2. Dodaj do głównej aktywności

    // MAIN ACTIVITY
    public class MyActivity extends ListActivity
    {
       ...
        SomeClass _some_class = new SomeClass();
        _someclass.setOnTaskFinishedEvent(new _some_class.OnTaskExecutionFinished()
        {
        @Override
        public void OnTaskFihishedEvent(String result)
        {
            Toast.makeText(getApplicationContext(),
                    "Phony thread finished: " + result,
                    Toast.LENGTH_SHORT).show();
        }
    
       });
       _some_class.execute();
       ...
     }
    
 2
Author: Oleg Karbushev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 23:13:31

Możesz napisać własnego słuchacza. Jest taka sama jak odpowiedź HelmiB, ale wygląda bardziej naturalnie:

Utwórz interfejs słuchacza:

public interface myAsyncTaskCompletedListener {
    void onMyAsynTaskCompleted(int responseCode, String result);
}

Następnie napisz swoje zadanie asynchroniczne:

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

    private myAsyncTaskCompletedListener listener;
    private int responseCode = 0;

    public myAsyncTask() {
    }

    public myAsyncTask(myAsyncTaskCompletedListener listener, int responseCode) {
        this.listener = listener;
        this.responseCode = responseCode;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }


    @Override
    protected String doInBackground(String... params) {
        String result;
        String param = (params.length == 0) ? null : params[0];
        if (param != null) {
            // Do some background jobs, like httprequest...
            return result;
        }
        return null;
    }

    @Override
    protected void onPostExecute(String finalResult) {
        super.onPostExecute(finalResult);
        if (!isCancelled()) {
            if (listener != null) {
                listener.onMyAsynTaskCompleted(responseCode, finalResult);
            }
        }
    }
}

Wreszcie zaimplementuj słuchacza w aktywności:

public class MainActivity extends AppCompatActivity implements myAsyncTaskCompletedListener {

    @Override
    public void onMyAsynTaskCompleted(int responseCode, String result) {

        switch (responseCode) {
            case TASK_CODE_ONE: 
                // Do something for CODE_ONE
                break;
            case TASK_CODE_TWO:
                // Do something for CODE_TWO
                break;
            default: 
                // Show some error code
        }        
    }

I tak można wywołać asyncTask:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Some other codes...
        new myAsyncTask(this,TASK_CODE_ONE).execute("Data for background job");
        // And some another codes...
}
 2
Author: Kuvalya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:50

Utwórz statyczny członek w klasie aktywności. Następnie przypisz wartość podczas onPostExecute

Na przykład, jeśli wynikiem Asynctasku jest łańcuch znaków, Utwórz publiczny łańcuch statyczny w aktywności

public static String dataFromAsyncTask;

Następnie, w onPostExecute AsyncTask, po prostu wykonaj statyczne wywołanie do swojej głównej klasy i ustaw wartość.

MainActivity.dataFromAsyncTask = "result blah";

 1
Author: mrres1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-25 01:38:08

I make it work by using threading and handler / message. Kroki w następujący sposób: Declare a progress Dialog

ProgressDialog loadingdialog;

Utwórz funkcję zamykającą okno dialogowe po zakończeniu operacji.

   private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        loadingdialog.dismiss();

    }
    };

Koduj Szczegóły Wykonania:

 public void startUpload(String filepath) {
    loadingdialog = ProgressDialog.show(MainActivity.this, "Uploading", "Uploading Please Wait", true);
    final String _path = filepath;
    new Thread() {
        public void run() {
            try {
                UploadFile(_path, getHostName(), getPortNo());
                handler.sendEmptyMessage(0);

            } catch (Exception e) {
                Log.e("threadmessage", e.getMessage());
            }
        }
    }.start();
}
 0
Author: RAY,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-09 13:37:06

Musisz użyć "protokołów" do delegowania lub przekazywania danych do AsynTask.

Delegaci i źródła danych

Delegat to obiekt, który działa w imieniu lub w koordynacji z innym obiektem, gdy ten obiekt napotka Zdarzenie w programie. (definicja jabłka )

Protokoły są interfejsami, które definiują niektóre metody delegowania niektórych zachowań.

Oto kompletny przykład!!!

 0
Author: IgniteCoders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 15:36:00