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

362

Tengo estas dos clases. Mi actividad principal y la que extiende el AsyncTask, ahora en mi actividad principal necesito obtener el resultado de OnPostExecute()la AsyncTask. ¿Cómo puedo pasar u obtener el resultado en 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<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);

}       

}   
Stella
fuente
Puede crear una interfaz como HelmiB explicó o puede crear un receptor de transmisión local Puede ver la implementación del receptor de transmisión de muestra aquí wiki.workassis.com/android-local-broadcast-receiver
Bikesh M
¿Por qué no usar el patrón Observador?
JAAAY

Respuestas:

751

Fácil:

  1. Crear interfaceclase, donde String outputes opcional, o puede ser cualquier variable que desee devolver.

    public interface AsyncResponse {
        void processFinish(String output);
    }
  2. Vaya a su AsyncTaskclase y declare la interfaz AsyncResponsecomo un campo:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
  3. En su actividad principal, necesita implementsinteractuar 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 forma simple y conveniente de usarinterface .

sigo usando lo mismo interface . Para su información, puede combinar esto en AsyncTaskclase.

en AsyncTaskclase:

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

haz esto en tu Activityclase

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 anteriores, la primera y la tercera, necesita crear un método processFinish , la otra, el método está dentro del parámetro del llamador. El tercero es más ordenado porque no hay una clase anónima anidada. Espero que esto ayude

Consejo : Cambie String output, String responsey String resulta diferentes tipos de coincidencia para obtener diferentes objetos.

HelmiB
fuente
20
Totalmente escribí todo eso y luego vi tu respuesta :) ¡Aquí hay que pensar igual! +1. ¡De esta manera, muchas cosas pueden escuchar los resultados de AsyncTask!
Roloc
8
Recibo una excepción de puntero nulo porque el delegado está establecido en nulo, por favor aclare
Reyjohn
2
Solo una nota para los desarrolladores de .net, uno puede usar AutoResetEvents para lograr esto y también hay una implementación de Java para autoresetevents, pero esto es mucho más limpio. Por cierto, ¿es seguro el hilo ProcessFinish?
Syler
13
para todos aquellos que obtienen un puntero nulo, pase su interfaz a su constructor de clase asyncTask, luego asígnelo a una variable y luego llame a processfinish () en esa variable. Para referencia ver aceptado como respuesta. stackoverflow.com/questions/9963691/…
Soleado
2
@Sunny tienes razón ... también, tenemos que inicializar el objeto asíncrono para async.delegate = this; a trabajar ..
Ninja_Coder
24

Hay algunas opciones:

  • Anida la AsyncTaskclase dentro de tu Activityclase. Suponiendo que no use la misma tarea en múltiples actividades, 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<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
  • Crea un constructor personalizado para tu AsyncTaskque tome una referencia a tu Activity. Instanciarías la tarea con algo así 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
        ...
    }
quietmint
fuente
En la segunda opción: ¿Por qué pasar por el dolor de un constructor y un campo si la clase no lo es static? Solo use cualquiera fieldOrMethodde MyActivityo MyActivity.this.fieldOrMethodsi está sombreado.
TWiStErRob
@TWiStErRob El segundo supone MyAsyncTaskque no es una clase interna.
quietmint
1
Oh, lo siento, private/ protectedpara las clases de nivel superior no está permitido, por lo tanto, pensé que debe ser una staticclase no interna.
TWiStErRob
2
Solo tenga cuidado de que la clase interna AsyncTask pueda ser una fuente de pérdidas de memoria como se explica aquí garena.github.io/blog/2014/09/10/android-memory-leaks
Mark Pazon
2
Aferrarse a una referencia de actividad también es una pérdida de memoria. El enfoque de devolución de llamada es mucho mejor que esto
OneCricketeer
19

Sentí que el siguiente enfoque es muy fácil.

He declarado una interfaz para devolución de llamada

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

Luego creó una tarea asincrónica para responder a todo tipo de solicitudes paralelas

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

}

Luego llamó a la tarea asincrónica 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

Arshad
fuente
17

Puedes probar este código en tu clase Main. 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();
}
Nicu P
fuente
2
¿Puede explicar por qué esto ayudaría a OP con su problema?
John Odom
3
Eso me ayudo. Intenté de otra manera como la respuesta de @HelmiB pero no obtuve resultados
Nicu P
Ok, perdón por mi respuesta. Necesita llamar a la clase AsyncTask y luego poner un parámetro a esta llamada. AsyncTask se define por 3 tipos genéricos: 1 params (dominio del servidor u otro param) 2 progresos (pueden ser nulos), 3 resultados. Todos estos tipos pueden ser: JSONObject, o cadenas, o cualquier tipo de datos. Cuando tiene una clase AsyncTask, debe definir dónde enviar los datos. ex: asyncTask.execute (" sampletargeturl.com"). get () ;
Nicu P
Al usar este método, recibí una advertencia en Logcat: "I / Choreographer ﹕ ¡Salteé 50 fotogramas! La aplicación puede estar haciendo demasiado trabajo en su hilo principal". Como lidiar con esto? ¿Se congela la interfaz de usuario cuando espero que devuelva AsyncTask?
Huy Do
@NicuP puede que te hayas olvidado de llamar execute(), mira mi respuesta, he agregado un comentario allí. es posible que desee verificar mi respuesta actualizada. espero que esto ayude.
HelmiB
16

Esta respuesta puede llegar tarde, pero me gustaría mencionar algunas cosas cuando Activitydepende de usted AsyncTask. Eso lo ayudaría a evitar bloqueos y administrar la memoria. Como ya se mencionó en las respuestas anteriores interface, también les decimos devoluciones de llamada. Trabajarán como informadores, pero nunca enviarán referencias fuertesActivity o interfacesiempre usarán débiles. referencias en esos casos.

Consulte la captura de pantalla a continuación para descubrir cómo eso puede causar problemas.

ingrese la descripción de la imagen aquí

Como puede ver si comenzamos AsyncTaskcon una referencia sólida, entonces no hay garantía de que nuestro Activity/ Fragmentestará vivo hasta que obtengamos datos, por lo que sería mejor usarlo WeakReferenceen esos casos y eso también ayudará en la administración de la memoria, ya que nunca lo mantendremos la fuerte referencia de nuestroActivity entonces será elegible para la recolección de basura después de su distorsión.

Consulte el fragmento de código a continuación para descubrir cómo usar la increíble WeakReference:

MyTaskInformer.java Interfaz que funcionará como informador.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.javaAsyncTask para hacer una tarea de larga duración, que utilizará 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.javaEsta clase se usa para iniciar mi AsyncTaskimplementación interfaceen esta clase y overrideeste 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);
    }
}
Rahul
fuente
2
¡Esto es genial! Un punto importante que no se puede notar.
HasH
6

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

} `

usuario3691697
fuente
6

Puede hacerlo en unas pocas líneas, simplemente anule onPostExecute cuando llame a su 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, feliz codificación :)

Ayaz Alifov
fuente
A mi no me funciona. Simplemente no ingresa al onPostExecutemétodo.
Francisco Romero
4

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

Esto debería ser suficiente.

No implemente onPostExecute en la tarea asíncrona, más bien impleméntelo 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");

}


}
bugdayci
fuente
Esto funciona para mi. Es lo más simple y fácil de entender. Creo que está haciendo uso de lo que Java está diseñado para hacer. Gracias. PD: ¿Es necesario agregar un @Override?
Old Geezer
1
No. @Override es solo una anotación. Entonces le está diciendo al compilador de Java que tiene la intención de anular el método e informarse si no lo está haciendo.
bugdayci
4

Puede llamar al get()método de AsyncTask(o al sobrecargado get(long, TimeUnit)). Este método se bloqueará hasta que AsyncTaskhaya completado su trabajo, en cuyo punto le devolverá elResult .

Sería aconsejable realizar otro trabajo entre la creación / inicio de su tarea asincrónica y llamar al getmétodo, de lo contrario no está utilizando la tarea asincrónica de manera muy eficiente.

nicholas.hauschild
fuente
1
Voto rechazado porque get () bloqueará el hilo principal. No hay razón para usar AsyncTask si se bloqueará
GabrielBB
3

Puedes escribir tu propio oyente. Es lo mismo que HelmiB la respuesta de pero parece 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<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);
            }
        }
    }
}

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 puede 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...
}
Kuvalya
fuente
2

Hola, puedes hacer algo como esto:

  1. Crear clase que implementa 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. Agregar 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();
       ...
     }
Oleg Karbushev
fuente
1

Cree un miembro estático en su clase de actividad. Luego asigne el valor durante elonPostExecute

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

public static String dataFromAsyncTask;

Luego, en onPostExecuteAsyncTask, simplemente haga una llamada estática a su clase principal y establezca el valor.

MainActivity.dataFromAsyncTask = "result blah";

mrres1
fuente
1
¿Cuáles son las posibilidades de pérdida de memoria en este escenario?
antroid
0

Lo hago funcionar mediante subprocesos y manejador / mensaje. 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 los detalles de su 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();
}
RAYO
fuente
0

Debe usar "protocolos" para delegar o proporcionar datos al AsynTask.

Delegados y fuentes de datos

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

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

Aquí hay un ejemplo completo !!!

IgniteCoders
fuente
0

prueba esto:

public class SomAsyncTask extends AsyncTask<String, Integer, JSONObject> {

    private CallBack callBack;

    public interface CallBack {
        void async( JSONObject jsonResult );
        void sync( JSONObject jsonResult );
        void progress( Integer... status );
        void cancel();
    }

    public SomAsyncTask(CallBack callBack) {
        this.callBack = callBack;
    }

    @Override
    protected JSONObject doInBackground(String... strings) {

        JSONObject dataJson = null;

        //TODO query, get some dataJson

        if(this.callBack != null)
            this.callBack.async( dataJson );// asynchronize with MAIN LOOP THREAD

        return dataJson;

    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        if(this.callBack != null)
            this.callBack.progress(values);// synchronize with MAIN LOOP THREAD

    }

    @Override
    protected void onPostExecute(JSONObject jsonObject) {
        super.onPostExecute(jsonObject);

        if(this.callBack != null)
            this.callBack.sync(jsonObject);// synchronize with MAIN LOOP THREAD
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();

        if(this.callBack != null)
            this.callBack.cancel();

    }
}

Y ejemplo de uso:

public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         final Context _localContext = getContext();
         SomeAsyncTask.CallBack someCallBack = new SomeAsyncTask.CallBack() {

                @Override
                public void async(JSONObject jsonResult) {//async thread
                    //some async process, e.g. send data to server...
                }

                @Override
                public void sync(JSONObject jsonResult) {//sync thread
                    //get result...

                    //get some resource of Activity variable...
                    Resources resources = _localContext.getResources();
                }

                @Override
                public void progress(Integer... status) {//sync thread
                    //e.g. change status progress bar...
                }

                @Override
                public void cancel() {

                }

            };

            new SomeAsyncTask( someCallBack )
                                .execute("someParams0", "someParams1", "someParams2");

    }
amiron
fuente
0

Probablemente exagere un poco, pero proporcioné devoluciones de llamadas tanto para el código de ejecución como para los resultados. obviamente, para la seguridad del subproceso, debe tener cuidado con lo que accede en la devolución de llamada de ejecución.

La implementación de AsyncTask:

public class AsyncDbCall<ExecuteType,ResultType> extends AsyncTask<ExecuteType, Void,  
ResultType>
{
    public interface ExecuteCallback<E, R>
    {
        public R execute(E executeInput);
    }
    public interface PostExecuteCallback<R>
    {
        public void finish(R result);
    }

    private PostExecuteCallback<ResultType> _resultCallback = null;
    private ExecuteCallback<ExecuteType,ResultType> _executeCallback = null;


    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback, PostExecuteCallback<ResultType> postExecuteCallback)
    {
        _resultCallback = postExecuteCallback;
        _executeCallback = executeCallback;
    }

    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback)
    {
        _executeCallback = executeCallback;
    }

    @Override
    protected ResultType doInBackground(final ExecuteType... params)
    {
        return  _executeCallback.execute(params[0]);
    }

    @Override
    protected void onPostExecute(ResultType result)
    {
        if(_resultCallback != null)
            _resultCallback.finish(result);
    }
}

Una devolución de llamada:

 AsyncDbCall.ExecuteCallback<Device, Device> updateDeviceCallback = new 
 AsyncDbCall.ExecuteCallback<Device, Device>()
    {
        @Override
        public Device execute(Device device)
        {
            deviceDao.updateDevice(device);
            return device;
        }
    };

Y finalmente la ejecución de la tarea asíncrona:

 new AsyncDbCall<>(addDeviceCallback, resultCallback).execute(device);
Squbly
fuente
0

Espero que hayas pasado por esto , si no, por favor lee.

https://developer.android.com/reference/android/os/AsyncTask

Dependiendo de la naturaleza de los datos de resultados, debe elegir la mejor opción posible que se le ocurra.

Es una gran opción usar una interfaz

algunas otras opciones serían ...

  • Si la clase AsyncTask se define dentro de la clase en la que desea utilizar el resultado. Utilice una variable global estática o get () , úsela desde la clase externa ( variable volátil si es necesario). pero debe tener en cuenta el progreso de AsyncTask o al menos asegurarse de que haya terminado la tarea y el resultado esté disponible a través del método global variable / get (). puede usar sondeo, onProgressUpdate (Progress ...) , sincronización o interfaces (lo que mejor le convenga)

  • Si el resultado es compatible para ser una entrada de referencia compartida o está bien que se guarde como un archivo en la memoria, puede guardarlo incluso desde la tarea en segundo plano y podría usar el método onPostExecute ()
    para recibir una notificación cuando el resultado esté disponible en la memoria.

  • Si la cadena es lo suficientemente pequeña y se debe utilizar al inicio de una actividad es posible usar intentos ( putExtra () ) dentro de onPostExecute () , pero recuerde que los contextos estáticos no son tan seguros de manejar.

  • Si es posible, puede llamar a un método estático desde el método onPostExecute (), siendo el resultado su parámetro

Duro
fuente