2010-04-27 8 views
6

¿Es posible, desde dentro de una AsyncTask que NO sea una clase interna de la clase de actividad llamante, obtener una referencia a la instancia de actividad iniciada? ejecución de AsyncTask?Obteniendo referencia a la actividad de llamada de AsyncTask (NO como clase interna)

Soy consciente de this thread, sin embargo, no trata exactamente cómo hacer referencia a la actividad de la llamada. Algunos sugieren pasar una referencia a la Actividad como un parámetro para el constructor AsyncTask, sin embargo, se informa que hacerlo siempre dará como resultado una NullPointerException.

Por lo tanto, estoy perdido. My AsyncTask proporciona una funcionalidad robusta, y no quiero tener que duplicarlo como clase interna en cada Actividad que quiera usar. Debe haber una solución elegante.

Respuesta

10

La "solución elegante" es en realidad tratar pasándole como parámetro (al constructor o execute()) y ver si funciona, en lugar de asumir la persona que hizo esa pregunta anterior (entonces respondió a su propia pregunta dos veces) sabe lo que está haciendo. No se me ocurre nada intrínseco a AsyncTask que pueda hacer que Activity sea un mal parámetro de constructor y que cualquier otro objeto esté bien.

Ahora, no he pasado una Activity (u otro Context) como un parámetro a un AsyncTask, porque mi AsyncTasks son siempre las clases internas privadas. De hecho, el hecho de que desee me llame públicamente AsyncTask es un olor a código, sugiriendo que estas tareas deberían estar mediadas por un Service o algún otro punto de control. Pero, ese soy solo yo.

ACTUALIZACIÓN

una mejor respuesta para el manejo de este patrón se puede encontrar aquí: Background task, progress dialog, orientation change - is there any 100% working solution?

+0

Punto tomada en un solo tratando * * por mí mismo en primer lugar. Tengo curiosidad sobre cómo manejarías mi situación: no es nada complejo; Básicamente estoy tratando de crear una DownloadFileTask para hacer una solicitud HTTP GET básica en las URL aprobadas, y luego la aplicación hará cosas diferentes con los archivos descargados en función de la actividad/estado actual. Tengo diferentes actividades que necesitan descargar archivos para diferentes propósitos. ¿Sería mejor hacerlo con un servicio o alguna otra solución? – stormin986

+4

Ah, ya veo. Tienes dos opciones como yo lo veo. Uno es hacer que 'DownloadFileTask' sea público pero abstracto, y tener implementaciones privadas de clase interna para cosas únicas de una actividad determinada. El otro es hacer público 'DownloadFileTask' y pasar * algo * al constructor. En este caso, para minimizar el acoplamiento, es posible que no desee pasar una 'Actividad', sino algún otro tipo de interfaz que limite lo que' 'AsyncTask' puede hacer. De esta forma, puede optar por implementar la interfaz en una 'Actividad', o como un objeto separado, o lo que sea. – CommonsWare

+0

CW, has sido muy útil en muchos de mis, ¡así que gracias! Si puedo pasar una instancia de mi actividad a una AsyncTask pública, creo que es la mejor manera de hacerlo. Mencionas minimizar el acoplamiento ... ¿Qué quieres decir exactamente con esto y qué tipo de situaciones generalmente quieres evitar con él? – stormin986

4

Mis AsyncTask s siempre viven en un paquete separado mientras que todavía unido a un tipo particular de Activity. Aceptan su instancia en constructor y tienda en una variable local.
Trate de pensar en términos de crear una clase abstracta Activity que encapsula cosas relacionadas con AsyncTask y se extiende por otras actividades.
así:

public abstract RemoteListActivity<T> extends ListActivity{ 

// calls AsyncTask, shows spinning progress dialog, etc 

protected abstract T someConcreteMethod(); 

} 

public final class CustomerListActivity extends RemoteListActivity<Customer>{ 

protected final Customer someConcreteMethod(); 

} 

Alternativamente, si las cosas no caben en una sola jerarquía, tienen una interfaz:

interface LazyLoadable { 
    void setLoadingState(); 
    void setDefaultState(); 
} 

public class MyActivity extends Activity implements LazyLoadable{ 
} 

public final class AsyncTask extends AsyncTask<Void, Void, Void>{ 

    private final LazyLoadable lazyLoadable; 

    public MyAsyncTask(Context ctx, LazyLoadable lazyLoadable){ 
     super(ctx); 
     this.lazyLoadable = lazyLoadable; 
    } 

} 
Cuestiones relacionadas