¿Cómo obtener el resultado de OnPostExecute () a la actividad principal porque AsyncTask es una clase separada?

Tengo estas dos clases. Mi actividad principal y la que extiende AsyncTask , ahora en mi actividad principal necesito obtener el resultado de OnPostExecute() en AsyncTask . ¿Cómo puedo pasar u obtener el resultado para mi actividad principal?

Aquí están los códigos de muestra.

Mi actividad principal

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

Esta es la clase AsyncTask

 public class AasyncTask extends AsyncTask { TextView dataDisplay; //store the data String soapAction = "http://sample.com"; //SOAPAction header line. String targetServer = "https://sampletargeturl.com"; //Target Server. //SOAP Request. String soapRequest = ""; @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); } } 

Fácil:

  1. Crear clase de interface , donde String output es opcional, o puede ser cualquier variable que desee devolver.

     public interface AsyncResponse { void processFinish(String output); } 
  2. Ve a tu clase AsyncTask y declara la interfaz AsyncResponse como un campo:

     public class MyAsyncTask extends AsyncTask { public AsyncResponse delegate = null; @Override protected void onPostExecute(String result) { delegate.processFinish(result); } } 
  3. En su actividad principal, necesita implements interfaz 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. } } 

ACTUALIZAR

No sabía que este es un favorito para muchos de ustedes. Así que aquí está la manera simple y conveniente de usar la interface .

sigue usando la misma interface . FYI, puedes combinar esto en la clase AsyncTask .

en la clase 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); } } 

haz esto en tu clase de 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(); } 

O implementando la interfaz en la Actividad nuevamente

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

Como puede ver 2 soluciones arriba, la primera y la tercera, necesita crear el método processFinish , la otra, el método está dentro del parámetro de la persona que llama. El tercero es más limpio porque no hay una clase anónima anidada. Espero que esto ayude

Consejo : Cambie String output , String response y String result a diferentes tipos de concordancia para obtener diferentes objetos.

Hay algunas opciones:

  • Anida la clase AsyncTask dentro de tu clase de Activity . Suponiendo que no utilice la misma tarea en actividades múltiples, esta es la forma más fácil. Todo su código permanece igual, solo mueve la clase de tarea existente para que sea una clase anidada dentro de la clase de su actividad.

     public class MyActivity extends Activity { // existing Activity code ... private class MyAsyncTask extends AsyncTask { // existing AsyncTask code ... } } 
  • Cree un constructor personalizado para su AsyncTask que tome como referencia su Activity . Instalarías la tarea con algo como new MyAsyncTask(this).execute(param1, param2) .

     public class MyAsyncTask extends AsyncTask { private Activity activity; public MyAsyncTask(Activity activity) { this.activity = activity; } // existing AsyncTask code ... } 

Sentí que el enfoque a continuación es muy fácil.

He declarado una interfaz para callback

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

A continuación, creó la tarea asíncrona para responder a todo tipo de solicitudes paralelas

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

Luego se llama a la tarea asíncrona al hacer clic en un botón en la clase de actividad.

 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

Puedes probar este código en tu clase principal. Eso funcionó para mí, pero he implementado métodos de otra manera

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

Puedes hacerlo en unas pocas líneas, solo anula el PostExecute cuando llames a tu AsyncTask. Aquí hay un ejemplo para ti:

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

Espero que te haya ayudado, codicia feliz 🙂

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

} `

¿Por qué la gente lo hace tan difícil?

Esto debería ser suficiente.

No implemente onPostExecute en la tarea asincrónica, más bien impleméntela en la Actividad:

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

Esta respuesta puede ser tardía, pero me gustaría mencionar algunas cosas cuando su Activity depende de AsyncTask . Eso lo ayudaría a prevenir lockings y administración de memoria. Como ya se mencionó en las respuestas anteriores, vaya con la interface , también las llamamos devoluciones de llamada. Trabajarán como informantes, pero nunca envíen una referencia fuerte de Activity o la interface siempre usa una referencia débil en esos casos.

Consulte la siguiente captura de pantalla para saber cómo puede causar problemas.

enter image description here

Como puede ver si comenzamos AsyncTask con una referencia fuerte, entonces no hay garantía de que nuestra Activity / Fragment estará vivo hasta que obtengamos datos, por lo que sería mejor usar WeakReference en esos casos y eso también ayudará en la administración de la memoria como nunca tendremos la referencia fuerte de nuestra Activity entonces será elegible para la recolección de basura después de su distorsión.

Revisa el siguiente fragmento de código para descubrir cómo usar la impresionante WeakReference –

Interfaz MyTaskInformer.java que funcionará como informante.

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

MySmallAsyncTask.java AsyncTask para realizar tareas de larga ejecución, que utilizará WeakReference .

 public class MySmallAsyncTask extends AsyncTask { // ***** Hold weak reference ***** private WeakReference 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 Esta clase se utiliza para iniciar mi interface implementación AsyncTask en esta clase y override este método obligatorio.

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

Puede llamar al método get() de AsyncTask (o el get(long, TimeUnit) sobrecargado get(long, TimeUnit) ). Este método se bloqueará hasta que AsyncTask haya completado su trabajo, y en ese momento le devolverá el Result .

Sería conveniente realizar otro trabajo entre la creación / inicio de la tarea asincrónica y la invocación del método get ; de lo contrario, no se está utilizando la tarea asincrónica de manera muy eficiente.

Hola, puedes hacer algo como esto:

  1. Crear clase que implemente AsyncTask

     // TASK public class SomeClass extends AsyncTask> { 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. Agregar en la actividad principal

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

Puedes escribir tu propio oyente. Es lo mismo que la respuesta de HelmiB , pero se ve más natural:

Crear interfaz de escucha:

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

Luego escribe tu tarea asincrónica:

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

Finalmente implementar oyente en actividad:

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

Y así es como puedes llamar 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... } 

Crea un miembro estático en tu clase de Actividad. A continuación, asigne el valor durante el onPostExecute

Por ejemplo, si el resultado de su AsyncTask es una Cadena, cree una cadena pública estática en su Actividad

public static String dataFromAsyncTask;

Luego, en el onPostExecute de AsyncTask, simplemente realice una llamada estática a su clase principal y establezca el valor.

MainActivity.dataFromAsyncTask = "result blah";

Lo hago funcionar usando threading y handler / message. Pasos de la siguiente manera: Declarar un diálogo de progreso

 ProgressDialog loadingdialog; 

Cree una función para cerrar el diálogo cuando finalice la operación.

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

Codifique sus detalles de ejecución:

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

Necesita usar “protocolos” para delegar o proporcionar datos a AsynTask .

Delegados y fonts de datos

Un delegado es un objeto que actúa en nombre de, o en coordinación con, otro objeto cuando ese objeto encuentra un evento en un progtwig. ( Definición de Apple )

Los protocolos son interfaces que definen algunos métodos para delegar algunos comportamientos.

¡Aquí hay un ejemplo completo!