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.