Abrufen des Kontexts in AsyncTask


82

Ich versuche, den Kontext in meiner AsyncTask der Klasse Opciones abzurufen (diese Klasse ist die einzige, die diese Aufgabe aufruft), aber ich weiß nicht, wie ich das machen soll. Ich habe folgenden Code gesehen:

      protected void onPostExecute(Long result) {

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

Aber es funktioniert nicht bei mir, heißt es: "No enclosing instance of the type Opciones in scope"


4
Ist Opciones eine Aktivität? Wenn nicht, müssen Sie einen Kontext an diese Klasse übergeben und diesen dann imAsyncTask
Torben Kohlmeier

Dies sieht aus wie eine Antwort stackoverflow.com/questions/45653121/…
Mangesh

Antworten:


175

Sie müssen folgende Dinge tun.

  • Wenn Sie AsyncTask verwenden möchten , erweitern Sie das in einer anderen Klasse, z . B. MyCustomTask .
  • Übergeben Sie im Konstruktor der neuen Klasse den Kontext

Beispiel

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

Und instanziieren Sie die Klasse, indem Sie folgen.

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

36
Beachten Sie, dass es viel besser wäre, eine nicht verschachtelte oder statische Klasse zu verwenden und mContext in einer WeakReference zu halten, um Speicherlecks zu vermeiden
BamsBamx

8
Halten des Kontexts in der verschachtelten statischen Klasse Warnung vor Speicherverlust
Amir Hossein Ghasemi

2
und auch das Halten einer nicht statischen Klasse in einer verschachtelten Klasse führt zu einer Warnung vor Speicherlecks in der gesamten Klasse! Also, was sollen wir Kontext ohne Speicherverlust verwenden?
Amir Hossein Ghasemi

1
Finden Sie einen Weg, um Speicherverluste zu beheben. Context sollte eine WeakReference-Klasse sein.
Amir Hossein Ghasemi

Dies ist keine verschachtelte statische Klasse. Seine öffentliche Klasse und muss getrennt von Aktivität definiert werden. Aber ja, aus Sicherheitsgründen können wir WeakReference verwenden.
Chintan Rathod

57

Wenn Sie einen schwachen Verweis auf die Host-Aktivität halten, werden Speicherverluste vermieden.

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
Was ist, wenn wir zwischen Aktivitäten wechseln (Asyntask stoppen und fortsetzen) und dann zurückkommen? Ist die schwache Referenz noch aktiv?
D4rWiNS

1
Gibt es einen Vorteil, wenn Sie die schwache Referenz an die Klasse übergeben, anstatt myActivity zu übergeben?
Suche nach Stille

1
@seekingStillness Durch schwache Referenzen kann die Aktivität weiterhin mit Müll gesammelt werden, wodurch ein Speicherverlust verhindert wird.
Sai

13

Da nur einer Activitydiese Aufgabe verwendet, machen Sie sie einfach zu einer inneren Klasse davonActivity

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

Dann haben Sie Zugriff auf Mitgliedsvariablen von ActivityundContext


2
Lint zeigt eine Warnung vor Speicherlecks an, wenn die AsyncTask-Klasse nicht statisch ist.
SapuSeven

@SapuSeven Denken Sie daran, dass dies nur eine Warnung ist . Ich persönlich denke nicht, dass es ein Problem sein sollte, wenn es richtig verwendet wird, wie AsyncTaskes für kurzlebige Operationen und oft zum Aktualisieren von Ansichten in einem Activity. Es ist oft eine gute Idee, sie abzubrechen, onPause()wenn sie noch laufen. Vielleicht irre ich mich, aber das waren schon immer meine Gedanken. Hier finden Sie weitere Informationen zu diesem Thema .
CodeMagic

-6

Du kannst schreiben getApplicationContex(). Oder Definieren Sie eine globale Variable.

Activity activity;

Und bei der onCreate()Veranstaltung

activity = this;

dann,

 protected void onPostExecute(Long result) {

    Toast.makeText(activity,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.