uzyskiwanie kontekstu w AsyncTask

83

Próbuję uzyskać kontekst w moim AsyncTask klasy o nazwie Opciones (ta klasa jest jedyną, która wywołuje to zadanie), ale nie wiem, jak to zrobić, widziałem taki kod:

      protected void onPostExecute(Long result) {

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

Ale to nie działa dla mnie, mówi: "No enclosing instance of the type Opciones in scope"

D4rWiNS
źródło
4
Czy Opciones to działalność? Jeśli nie, musisz przekazać kontekst do tej klasy, a następnie użyć go wAsyncTask
Torben Kohlmeier.
To wygląda na odpowiedź stackoverflow.com/questions/45653121/ ...
Mangesh

Odpowiedzi:

176

Musisz wykonać następujące czynności.

  • jeśli chcesz użyć AsyncTask , rozszerz to w innej klasie, powiedz MyCustomTask .
  • w konstruktorze nowej klasy przekaż Context

Przykład

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

I utwórz instancję klasy, wykonując następujące czynności.

MyCustomTask task = new MyCustomTask(context);
task.execute(..);
Chintan Rathod
źródło
36
zauważ, że znacznie lepiej byłoby użyć niezagnieżdżonej lub statycznej klasy i przechowywać mContext w WeakReference, aby uniknąć wycieków pamięci
BamsBamx,
8
Trzymanie kontekstu w zagnieżdżonej klasie statycznej ostrzeżenie o wycieku pamięci
Amir Hossein Ghasemi
2
a także trzymanie klasy niestatycznej w klasie zagnieżdżonej powoduje ostrzeżenie o wycieku pamięci całej klasy! więc co powinniśmy używać kontekstu bez wycieku pamięci !?
Amir Hossein Ghasemi
1
Znajdź sposób na rozwiązanie problemu wycieku pamięci, Context powinien być klasą WeakReference.
Amir Hossein Ghasemi
To nie będzie zagnieżdżona klasa statyczna. Jego klasa publiczna i należy ją zdefiniować oddzielnie od czynności. Ale tak, dla bezpieczniejszej strony możemy użyć WeakReference.
Chintan Rathod
59

Utrzymanie słabego odniesienia do działania hosta zapobiegnie wyciekom pamięci.

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
źródło
1
A co z sytuacją, gdy przełączamy się między działaniami (zatrzymywanie i wznawianie zadania), a następnie wracamy, czy słabe odniesienie jest nadal aktywne?
D4rWiNS
1
Czy istnieje korzyść z przekazania elementu lowReference do klasy zamiast przekazywania myActivity?
LookingStillness
1
@seekingStillness Słabe odwołania nadal będą zezwalać na gromadzenie elementów bezużytecznych dla działania, zapobiegając w ten sposób wyciekowi pamięci.
Sai
13

Ponieważ tylko jeden Activityużywa tego zadania, po prostu uczyń go wewnętrzną klasą tegoActivity

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

Następnie masz dostęp do zmiennych składowych Activityi jegoContext

codeMagic
źródło
2
Lint wyświetla ostrzeżenie o wyciekach pamięci, jeśli klasa AsyncTask nie jest statyczna.
SapuSeven
@SapuSeven Pamiętaj, że to tylko ostrzeżenie . Osobiście uważam, że nie powinno to stanowić problemu, jeśli jest używane poprawnie, tak jak w AsyncTaskprzypadku operacji krótkotrwałych i często w przypadku aktualizowania widoków w pliku Activity. Często dobrym pomysłem jest anulowanie ich, onPause()jeśli nadal działają. Może się mylę, ale zawsze takie były moje przemyślenia. Tutaj można przeczytać więcej na ten temat .
codeMagic
-6

Możesz pisać getApplicationContex(). Lub Zdefiniuj zmienną globalną.

Activity activity;

I w onCreate()funkcji

activity = this;

następnie,

 protected void onPostExecute(Long result) {

    Toast.makeText(activity,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
}
yahya.can
źródło