obtener contexto en AsyncTask


83

Estoy tratando de obtener el contexto en mi AsyncTask de la clase llamada Opciones (esta clase es la única que llama a esa tarea) pero no sé cómo hacerlo, vi un código como este:

      protected void onPostExecute(Long result) {

    Toast.makeText(Opciones.this,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
}

Pero no me funciona, dice: "No enclosing instance of the type Opciones in scope"


4
¿Opciones es una actividad? De lo contrario, debe pasar un contexto a esa clase y luego usarlo en elAsyncTask
— Torben Kohlmeier

Respuestas:


176

Necesitas hacer las siguientes cosas.

  • cuando quiera usar AsyncTask , extienda eso en otra clase diga MyCustomTask .
  • en el constructor de la nueva clase, pase el contexto

Ejemplo

public class MyCustomTask extends AsyncTask<Void, Void, Long> {

    private Context mContext;

    public MyCustomTask (Context context){
         mContext = context;
    }

    //other methods like onPreExecute etc.
    protected void onPostExecute(Long result) {
         Toast.makeText(mContext,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
    }
}

E instancia la clase siguiendo.

MyCustomTask task = new MyCustomTask(context);
task.execute(..);

36
tenga en cuenta que sería mucho mejor usar una clase estática o no anidada y mantener mContext en una WeakReference para evitar pérdidas de memoria
— BamsBamx

8
Mantener el contexto en una clase estática anidada arrojar una advertencia de fuga de memoria
— Amir Hossein Ghasemi

2
y también mantener una clase no estática en una clase anidada porque ¡advertencia de pérdidas de memoria de toda la clase! Entonces, ¿qué deberíamos usar el contexto sin pérdida de memoria?
— Amir Hossein Ghasemi

1
Encuentre una manera de resolver la pérdida de memoria, el contexto debe ser una clase WeakReference.
— Amir Hossein Ghasemi

Esta no será una clase estática anidada. Su clase pública y debe definirse por separado de la actividad. Pero sí, para un lado más seguro, podemos usar WeakReference.
— Chintan Rathod

59

Mantener una referencia débil a la actividad del host evitará pérdidas de memoria.

static class MyTask extends AsyncTask<Void, Void, Void> {
    // Weak references will still allow the Activity to be garbage-collected
    private final WeakReference<Activity> weakActivity;

    MyTask(Activity myActivity) {
      this.weakActivity = new WeakReference<>(myActivity);
    }

    @Override
    public Void doInBackground(Void... params) {
      // do async stuff here
    }

    @Override
    public void onPostExecute(Void result) {
      // Re-acquire a strong reference to the activity, and verify
      // that it still exists and is active.
      Activity activity = weakActivity.get();
      if (activity == null
          || activity.isFinishing()
          || activity.isDestroyed()) {
        // activity is no longer valid, don't do anything!
        return;
      }

      // The activity is still valid, do main-thread stuff here
    }
  }

1
¿Qué pasa cuando cambiamos entre actividades (detener y reanudar una fantasía) y luego volvemos? ¿Sigue activa la referencia débil?
— D4rWiNS

1
¿Hay algún beneficio para pasar la débilReferencia a la clase en lugar de pasar myActivity?
— LookingStillness

1
@seekingStillness Las referencias débiles aún permitirán que la Actividad sea recolectada como basura evitando así una pérdida de memoria.
— Sai

13

Dado que solo uno Activityusa esta tarea, conviértalo en una clase interna de eseActivity

public class Opciones extends Activity
{
     public void onCreate()
     {
         ...
     }

    public class MyTask extends AsyncTask<>
    {
        ...

         protected void onPostExecute(Long result) {
        Toast.makeText(Opciones.this,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
     }
}

Entonces tienes acceso a las variables miembro de Activityy suContext


2
Lint muestra una advertencia sobre pérdidas de memoria si la clase AsyncTask no es estática.
— SapuSeven

@SapuSeven Recuerda que es solo una advertencia . Personalmente, no creo que deba ser un problema si se usa correctamente AsyncTaskpara operaciones de corta duración y, a menudo, para actualizar vistas en un archivo Activity. A menudo, es una buena idea cancelarlos onPause()si aún se están ejecutando. Quizás me equivoque, pero esos siempre han sido mis pensamientos al respecto. Aquí hay más lecturas sobre el tema .
— codeMagic

-6

Puedes escribir getApplicationContex(). O Definir variable global.

Activity activity;

Y en la onCreate()función

activity = this;

entonces,

 protected void onPostExecute(Long result) {

    Toast.makeText(activity,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.