Как получить результат OnPostExecute () для основного действия, потому что AsyncTask – это отдельный класс?

У меня есть два класса. Моя основная деятельность и та, которая расширяет AsyncTask , Теперь в моей основной деятельности мне нужно получить результат из OnPostExecute() в AsyncTask . Как я могу передать или получить результат в свою основную деятельность?

Вот пример кода.

Моя основная деятельность.

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

Это класс 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); } } 

Solutions Collecting From Web of "Как получить результат OnPostExecute () для основного действия, потому что AsyncTask – это отдельный класс?"

Легко:

  1. Создайте класс interface , где String output является необязательным или может быть любыми переменными, которые вы хотите вернуть.

     public interface AsyncResponse { void processFinish(String output); } 
  2. Перейдите к классу AsyncTask и объявите интерфейс AsyncResponse как поле:

     public class MyAsyncTask extends AsyncTask{ public AsyncResponse delegate = null; @Override protected void onPostExecute(String result) { delegate.processFinish(result); } } 
  3. В вашей основной деятельности вам необходимо implements интерфейс 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. } } 

ОБНОВИТЬ

Я не знал, что это такой фаворит для многих из вас. Итак, вот простой и удобный способ использования interface .

Все еще используя тот же interface . FYI, вы можете объединить это в класс AsyncTask .

AsyncTask классе AsyncTask :

 public class MyAsyncTask extends AsyncTask{ // 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); } } 

Сделайте это в своем классе 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(); } 

Или, снова реализуя интерфейс для Activity

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

Поскольку вы видите два решения выше, первое и третье, ему нужно создать метод processFinish , другой – метод внутри параметра вызывающего. Третий более аккуратный, потому что нет вложенного анонимного класса. Надеюсь это поможет

Есть несколько вариантов:

  • AsyncTask класс AsyncTask класс Activity . Предполагая, что вы не используете одну и ту же задачу в нескольких действиях, это самый простой способ. Весь ваш код остается прежним, вы просто перемещаете существующий класс задач как вложенный класс внутри класса вашей деятельности.

     public class MyActivity extends Activity { // existing Activity code ... private class MyAsyncTask extends AsyncTask<String, Void, String> { // existing AsyncTask code ... } } 
  • Создайте настраиваемый конструктор для вашей AsyncTask который ссылается на вашу Activity . Вы должны создать экземпляр задачи с чем-то вроде 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 ... } 

Я чувствовал, что подход ниже очень прост.

Я объявил интерфейс для обратного вызова

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

Затем была создана асинхронная задача для ответа на все типы параллельных запросов

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

Затем вызывается асинхронная задача при нажатии кнопки в классе активности.

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

благодаря

Вы можете попробовать этот код в своем основном классе. Это сработало для меня, но я реализовал методы другим способом

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

Вы можете сделать это в нескольких строках, просто переопределите onPostExecute при вызове AsyncTask. Вот вам пример:

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

Надеюсь, это помогло вам, счастливая трещина 🙂

В вашем 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(); 

} `

Привет, вы можете сделать что-то вроде этого:

  1. Создать класс, который реализует 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. Добавить в основную деятельность

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

Вы можете написать свой собственный слушатель. Это то же самое, что и ответ HelmiB , но выглядит более естественным:

Создать интерфейс прослушивателя:

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

Затем напишите асинхронную задачу:

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

В завершение реализовать слушателя в действии:

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

И так вы можете вызвать 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... } 

Создайте статический член в своем классе Activity. Затем назначьте значение во время onPostExecute

Например, если результатом вашей AsyncTask является String, создайте общедоступную статическую строку в вашей деятельности

public static String dataFromAsyncTask;

Затем в onPostExecute AsyncTask просто сделайте статический вызов вашему основному классу и установите значение.

MainActivity.dataFromAsyncTask = "result blah";

Вы можете вызвать метод get() AsyncTask (или перегруженный get(long, TimeUnit) ). Этот метод будет блокироваться до тех пор, пока AsyncTask не завершит свою работу, и в этот момент он вернет вам Result .

Я заставляю его работать, используя потоки и обработчик / сообщение. Шаги, следующие: Объявите диалог прогресса

 ProgressDialog loadingdialog; 

Создайте функцию, чтобы закрыть диалог, когда операция завершена.

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

Скомпилируйте информацию об исполнении:

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

Почему люди делают это так сложно.

Этого должно быть достаточно.

Не выполняйте onPostExecute в задаче async, скорее реализуйте ее в Activity:

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

Этот ответ может быть запоздалым, но я хотел бы упомянуть несколько вещей, когда ваша Activity зависит от AsyncTask . Это поможет вам предотвратить сбои и управление памятью. Как уже упоминалось выше, ответы идут с interface , мы также говорим о них обратные вызовы. Они будут работать как информатор, но никогда не присылают сильную ссылку на Activity или interface всегда используют слабую ссылку в этих случаях.

См. Ниже скриншот, чтобы узнать, как это может вызвать проблемы.

Введите описание изображения здесь

Как вы можете видеть, если мы начали использовать AsyncTask с сильной ссылкой, то нет никакой гарантии, что наш Activity / Fragment будет жив, пока мы не получим данные, поэтому было бы лучше использовать WeakReference в этих случаях, а это также поможет в управлении памятью как Мы никогда не будем придерживаться сильной ссылки на нашу Activity тогда она будет иметь право на сбор мусора после ее искажения.

Проверьте ниже фрагмент кода, чтобы узнать, как использовать awesome WeakReference –

Интерфейс MyTaskInformer.java который будет работать как информатор.

 public interface MyTaskInformer { void onTaskDone(String output); } 

MySmallAsyncTask.java AsyncTask выполняет длительную задачу, которая будет использовать 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 Этот класс используется для запуска interface реализации AsyncTask в этом классе и override этого обязательного метода.

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