Cómo manejar el valor de retorno de AsyncTask

Estoy usando la clase AsyncTask con la siguiente firma:

 public class ApiAccess extends AsyncTask<List, Integer, String> { ... private String POST(List[] nameValuePairs){ ... return response; } } protected String doInBackground(List... nameValuePairs) { return POST(params); } 

Estoy tratando de llamarlo desde otra clase a través de:

 ApiAccess apiObj = new ApiAccess (0, "/User"); // String signupResponse = apiObj.execute(nameValuePairs); String serverResponse = apiObj.execute(nameValuePairs); //ERROR 

Pero aquí recibo este error:

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

¿Por qué es eso cuando he especificado String como el tercer parámetro en la línea de extensión de clase?

Puede obtener el resultado llamando al método get () de AsyhncTask en la AsyncTask devuelta, pero lo convertirá de una tarea asíncrona en una tarea síncrona mientras espera obtener el resultado.

 String serverResponse = apiObj.execute(nameValuePairs).get(); 

Como tiene su AsyncTask en una clase separada, puede crear una clase de interfaz y declararla en AsyncTask e implementar su nueva clase de interfaz como delegado en la clase a la que desea acceder. Una buena guía está aquí: ¿Cómo obtener el resultado de OnPostExecute () a la actividad principal porque AsyncTask es una clase separada? .

Intentaré aplicar el enlace de arriba a tu contexto.

(IApiAccessResponse)

 public interface IApiAccessResponse { void postResult(String asyncresult); } 

(ApiAccess)

 public class ApiAccess extends AsyncTask, Integer, String> { ... public IApiAccessResponse delegate=null; protected String doInBackground(List... nameValuePairs) { //do all your background manipulation and return a String response return response } @Override protected void onPostExecute(String result) { if(delegate!=null) { delegate.postResult(result); } else { Log.e("ApiAccess", "You have not assigned IApiAccessResponse delegate"); } } } 

(Tu clase principal, que implementa IApiAccessResponse)

 ApiAccess apiObj = new ApiAccess (0, "/User"); //Assign the AsyncTask's delegate to your class's context (this links your asynctask and this class together) apiObj.delegate = this; apiObj.execute(nameValuePairs); //ERROR //this method has to be implement so that the results can be called to this class void postResult(String asyncresult){ //This method will get call as soon as your AsyncTask is complete. asyncresult will be your result. } 

Sugeriría implementar una callback de Handler. Pasaría el controlador del fragmento (o de la actividad) a AsyncTask, que AsyncTask llamará cuando haya terminado. AsyncTask también puede devolver un objeto arbitrario.

Aquí hay un ejemplo de AsyncTask, que tengo en su propio archivo (no subclasificado):

 public class MyTask extends AsyncTask { private static final String TAG = "MyTask"; private Handler mCallersHandler; private Candy mObject1; private Popsicle mObject2; // Return codes public static final int MSG_FINISHED = 1001; public SaveVideoTask(Handler handler, Candy candyCane, Popsicle grapePop ) { this.mCallersHandler = handler; this.mObject1 = candyCane; this.mObject2 = grapePop; } @Override protected String doInBackground(Void... params) { // Do all of the processing that you want to do... // You already have the private fields because of the constructor // so you can use mObject1 and mObject2 Dessert objectToReturn = mObject1 + mObject2; // Tell the handler (usually from the calling thread) that we are finished, // returning an object with the message mCallersHandler.sendMessage( Message.obtain( mCallersHandler, MSG_FINISHED, objectToReturn ) ); return (null); } } 

Este ejemplo asume que tu AsyncTask necesita una pieza de Caramelo y una paleta. Luego devolverá un postre a su fragmento.

Puede construir y ejecutar AsyncTask en una línea desde su fragmento con:

 ( new MyTask( mFragmentHandler, candyCane, grapePop ) ).execute(); 

Pero, por supuesto, primero tendrá que configurar el controlador del fragmento (myFragmentHandler). Para hacer esto, su fragmento (o actividad) debería verse como (NOTA: “implementa Handler.Callback”):

 public class MyFragment extends Fragment implements Handler.Callback { private Handler mFragmentHandler; private Candy candyCane; private Popsicle grapePop; @Override public void onCreate(Bundle savedInstanceState) { // Standard creation code super.onCreate(savedInstanceState); setRetainInstance(true); // Create a handler for this fragment mFragmentHandler = new Handler(this); // Other stuff... } @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { // Inflate the layout View v = inflater.inflate(R.layout.my_fragment_layout, parent, false ); // The candyCane and grapePop don't need to be set up here, but // they MUST be set up before the button is pressed. // Here would be a good place to at least initialize them... // Perhaps you have a button in "my_fragment_layout" that triggers the AsyncTask... Button mButton = (Button) v.findViewById(R.id.mButton); mButton.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { ( new MyTask( mFragmentHandler, candyCane, grapePop ) ).execute(); } }); return v; } @SuppressWarnings("unchecked") @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MyTask.MSG_FINISHED: // Let's see what we are having for dessert Dessert myDessert = (Dessert) msg.obj; break; } return false; } } 

Si usa estos fragmentos de código, al presionar un botón se activará la AsyncTask. El fragmento de llamada continuará ejecutándose mientras se procesa AsyncTask. Luego, cuando la AsyncTask finalice, enviará un mensaje al fragmento diciendo que está terminado, y pasará un objeto con el mensaje. En este punto, el fragmento verá el mensaje y hará lo que quiera.

Nota: Puede haber errores tipográficos. Esto está cortado de un código muy grande y complicado.

Por favor, lea AsyncTask . Puede obtener el resultado en el método onPostExecute . No puedes hacer algo como:

 String serverResponse = apiObj.execute(nameValuePairs); 

porque es asincrónico

El problema es que cuando se ejecuta ejecutar, se devuelve el objeto AsyncTask, pero aún no el resultado. El resultado se calcula en segundo plano. El tipo del resultado eventualmente será una Cadena (como usted especificó), y se pasará a onPostExecute() .

Debe usar AsyncTask siguiente manera:

 public class ApiAccess extends AsyncTask, Integer, String> { ... private String POST(List[] nameValuePairs){ ... return response; } protected void onPreExecute (){ // this is run on the main (UI) thread, before doInBackground starts } protected void onPostExecute (String result){ // this is run on the main (UI) thread, after doInBackground returns } protected String doInBackground(List... nameValuePairs) { // run in another, background thread return POST(params); } } 

Tenga en cuenta que en su ejemplo no está devolviendo el resultado en doInBackground() , que debería.