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"


4
Czy Opciones to działalność? Jeśli nie, musisz przekazać kontekst do tej klasy, a następnie użyć go wAsyncTask
Torben Kohlmeier.

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

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
    }
  }

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


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(); 
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.