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"

D4rWiNS
fuente
4
¿Opciones es una actividad? De lo contrario, debe pasar un contexto a esa clase y luego usarlo en elAsyncTask
Torben Kohlmeier
Esto parece una respuesta stackoverflow.com/questions/45653121/…
Mangesh

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(..);
Chintan Rathod
fuente
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
    }
  }
Sai
fuente
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

codeMagic
fuente
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(); 
}
yahya.can
fuente