thread - asynctask android enviando devoluciones de llamada a ui
manejo de asynctask (4)
Esta pregunta ya tiene una respuesta aquí:
Tengo la siguiente clase asynctask que no está dentro de la actividad. En la actividad estoy inicializando la asynctask, y quiero que asynctask registre las devoluciones de llamadas a mi actividad. ¿Es posible? ¿O la asynctask debe estar en el mismo archivo de clase que la actividad?
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
caller.sometextfield.setText("bla");
}
¿Algo como esto?
Al completar las respuestas anteriores, también puede personalizar sus errores para cada llamada asíncrona que realice, de modo que cada llamada al método genérico ASYNC llene datos diferentes, dependiendo de las cosas en el teclado que ponga ahí.
Main.FragmentCallback FC= new Main.FragmentCallback(){
@Override
public void onTaskDone(String results) {
localText.setText(results); //example TextView
}
};
new API_CALL(this.getApplicationContext(), "GET",FC).execute("&Books=" + Main.Books + "&args=" + profile_id);
Recuerda: utilicé la interfaz en la actividad principal que es donde viene "Main", así:
public interface FragmentCallback {
public void onTaskDone(String results);
}
Mi publicación de API se ve así:
@Override
protected void onPostExecute(String results) {
Log.i("TASK Result", results);
mFragmentCallback.onTaskDone(results);
}
El constructor de API se ve así:
class API_CALL extends AsyncTask<String,Void,String> {
private Main.FragmentCallback mFragmentCallback;
private Context act;
private String method;
public API_CALL(Context ctx, String api_method,Main.FragmentCallback fragmentCallback) {
act=ctx;
method=api_method;
mFragmentCallback = fragmentCallback;
}
Puede crear una interface
, pasarla a AsyncTask
(en constructor) y luego llamar al método en onPostExecute()
Por ejemplo:
Su interfaz:
public interface OnTaskCompleted{
void onTaskCompleted();
}
Tu actividad:
public class YourActivity implements OnTaskCompleted{
// your Activity
}
Y tu AsyncTask:
public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type
private OnTaskCompleted listener;
public YourTask(OnTaskCompleted listener){
this.listener=listener;
}
// required methods
protected void onPostExecute(Object o){
// your stuff
listener.onTaskCompleted();
}
}
EDITAR
Como esta respuesta se hizo bastante popular, quiero agregar algunas cosas.
Si eres nuevo en el desarrollo de Android, AsyncTask
es una forma rápida de hacer que las cosas funcionen sin bloquear el hilo de UI. Resuelve algunos problemas, no hay nada de malo en cómo funciona la clase. Sin embargo, trae algunas implicaciones, tales como:
- Posibilidad de pérdida de memoria. Si mantiene referencia a su
Activity
, permanecerá en la memoria incluso después de que el usuario haya salido de la pantalla (o haya rotado el dispositivo). -
AsyncTask
no está entregando el resultado a laActivity
si laActivity
ya fue destruida. Tienes que agregar un código extra para administrar todo esto o hacer dos operaciones. - Código complicado que hace todo en
Activity
Cuando sienta que ha madurado lo suficiente como para seguir con Android, eche un vistazo a este artículo que, en mi opinión, es una mejor manera de desarrollar sus aplicaciones de Android con operaciones asincrónicas.
Sentí que el enfoque a continuación es muy fácil.
He declarado una interfaz para devolución de llamada
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<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 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[] { "Youe request to aynchronous task class is giving here.." });
}
});
}
}
Gracias
Voy a repetir lo que dijeron los demás, pero intentaré simplificarlo ...
Primero, solo crea la clase de interfaz
public interface PostTaskListener<K> {
// K is the type of the result object of the async task
void onPostTask(K result);
}
En segundo lugar, crea AsyncTask (que puede ser una clase estática interna de tu actividad o fragmento) que utiliza la interfaz, incluyendo una clase concreta. En el ejemplo, PostTaskListener está parametrizado con String, lo que significa que espera una clase String como resultado de la tarea asincrónica.
public static class LoadData extends AsyncTask<Void, Void, String> {
private PostTaskListener<String> postTaskListener;
protected LoadData(PostTaskListener<String> postTaskListener){
this.postTaskListener = postTaskListener;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null && postTaskListener != null)
postTaskListener.onPostTask(result);
}
}
Finalmente, la parte en donde combinas tu lógica. En su actividad / fragmento, cree PostTaskListener y páselo a la tarea asíncrona. Aquí hay un ejemplo:
...
PostTaskListener<String> postTaskListener = new PostTaskListener<String>() {
@Override
public void onPostTask(String result) {
//Your post execution task code
}
}
// Create the async task and pass it the post task listener.
new LoadData(postTaskListener);
¡Hecho!