Unterschied zwischen getContext (), getApplicationContext (), getBaseContext () und "this"


565

Was ist der Unterschied zwischen getContext(), getApplicationContext(), getBaseContext()und " this?“

Obwohl dies eine einfache Frage ist, kann ich den grundlegenden Unterschied zwischen ihnen nicht verstehen. Bitte geben Sie nach Möglichkeit einige einfache Beispiele an.


1
Es gibt eine ausgezeichnete Beschreibung in der ersten Antwort: stackoverflow.com/questions/1026973/…
ky1enamic

Antworten:


528
  • View.getContext(): Gibt den Kontext zurück, in dem die Ansicht gerade ausgeführt wird. Normalerweise die aktuell aktive Aktivität.

  • Activity.getApplicationContext(): Gibt den Kontext für die gesamte Anwendung zurück (der Prozess, in dem alle Aktivitäten ausgeführt werden). Verwenden Sie diese Option anstelle des aktuellen Aktivitätskontexts, wenn Sie einen Kontext benötigen, der an den Lebenszyklus der gesamten Anwendung gebunden ist, nicht nur an die aktuelle Aktivität.

  • ContextWrapper.getBaseContext(): Wenn Sie aus einem anderen Kontext heraus auf einen Kontext zugreifen müssen, verwenden Sie einen ContextWrapper. Auf den Kontext, auf den in diesem ContextWrapper verwiesen wird, wird über getBaseContext () zugegriffen.


59
und was ist mit "dem"?
CooL i3oY

16
+ CooL i3oY gleich mit getContext
Mikey

13
Eigentlich bin ich verwirrt, was ist die richtige Definition des Kontextes?
Ravi

11
"this" und getContext () sind beide gleich
KCRaju

43
thisund getContext()sind nicht immer gleich, zB in der Aktivitätsklasse, die Sie verwenden können, thisweil Activityerbt von, Contextaber die Methode getContext()ist nicht in der ActivityKlasse. @mikedroid @KCRaju
Nandan

92

Die meisten Antworten decken bereits ab getContext()und getApplicationContext()doch getBaseContext () wird selten erklärt.

Die Methode getBaseContext()ist nur relevant, wenn Sie eine haben ContextWrapper. Android bietet eine ContextWrapperKlasse, die um eine vorhandene ContextVerwendung erstellt wird:

ContextWrapper wrapper = new ContextWrapper(context);

Der Vorteil der Verwendung von a ContextWrapperbesteht darin, dass Sie das Verhalten ändern können, ohne den ursprünglichen Kontext zu ändern. Wenn Sie beispielsweise eine Aktivität namens aufgerufen haben, myActivitykönnen Sie eine Viewmit einem anderen Thema erstellen als myActivity:

ContextWrapper customTheme = new ContextWrapper(myActivity) {
  @Override
  public Resources.Theme getTheme() { 
    return someTheme;
  }
}
View myView = new MyView(customTheme);

ContextWrapperwirklich mächtig ist , weil es Ihnen , bereitgestellt durch die meisten Funktionen können außer Kraft setzen , Contexteinschließlich Code den Zugriff auf Ressourcen (zB openFileInput(), getString()), die Interaktion mit anderen Komponenten (zB sendBroadcast(), registerReceiver()), Anfragen Berechtigungen (zB checkCallingOrSelfPermission()) und Auflösen von Dateisystem - Standorten (zB getFilesDir()). ContextWrapperist sehr nützlich, um geräte- / versionenspezifische Probleme zu umgehen oder einmalige Anpassungen auf Komponenten wie Ansichten anzuwenden, für die ein Kontext erforderlich ist.

Die Methode getBaseContext () kann verwendet werden, um auf den Basiskontext zuzugreifen, den der ContextWrapperWraps umgibt . Möglicherweise müssen Sie auf den Basiskontext zugreifen, wenn Sie beispielsweise überprüfen möchten, ob es sich um einen handelt Service, Activityoder Application:

public class CustomToast {
  public void makeText(Context context, int resId, int duration) {
    while (context instanceof ContextWrapper) {
      context = context.baseContext();
    }
    if (context instanceof Service)) {
      throw new RuntimeException("Cannot call this from a service");
    }
    ...
  }
}

Oder wenn Sie die "unverpackte" Version einer Methode aufrufen müssen:

class MyCustomWrapper extends ContextWrapper {
  @Override
  public Drawable getWallpaper() {
    if (BuildInfo.DEBUG) {
      return mDebugBackground;
    } else {
      return getBaseContext().getWallpaper();
    }
  }
}

17
Ich würde sagen, dies ist die wichtigste Antwort nach einer akzeptierten.
0leg

4
Ich würde sagen, dass die Existenz von ContextWrappereine der schlimmsten Entscheidungen ist, die Entwickler von Android Framework jemals getroffen haben. Als sie feststellten, dass sie eine ganze Familie von Gottobjekten erstellt hatten, anstatt das Richtige zu tun und den Code in Richtung Einzelverantwortung umzugestalten, fügten sie einen hässlichen Hack hinzu, der es ermöglichte, das Kontextverhalten durch Vertiefung des Vererbungsbaums zu ändern. Schlechtes Software-Engineering in seiner hässlichsten Form. Was uns Entwickler betrifft, sollte IMHO niemand jemals verwenden getBaseContext()oder ContextWrapper. Wenn Sie dies tun, ist es ein riesiger "Code-Geruch".
Vasiliy

Ich möchte den vollständigen CustomToastCode sehen. Ston :))
Alston

39

getApplicationContext () - Gibt den Kontext für alle Aktivitäten zurück, die in der Anwendung ausgeführt werden.

getBaseContext () - Wenn Sie von einem anderen Kontext innerhalb der Anwendung aus auf Context zugreifen möchten, können Sie darauf zugreifen.

getContext () - Gibt nur die aktuelle laufende Aktivität der Kontextansicht zurück.


1
Bitte nehmen Sie die Buchstaben A und B in Ihre Definition des Kontexts mit auf. In keiner Antwort ist klar, auf welchen Kontext zugegriffen wird.
Hoffentlich

29

Die Frage "Was ist der Kontext?" Ist eine der schwierigsten Fragen im Android-Universum.

Der Kontext definiert Methoden, die auf Systemressourcen zugreifen, statische Assets der Anwendung abrufen, Berechtigungen überprüfen, Benutzeroberflächenmanipulationen durchführen und vieles mehr. Im Wesentlichen,Context ist ein Beispiel für God Object Anti-Muster in der Produktion.

Wenn es darum geht, welche Art von ContextVerwendung wir verwenden sollen, wird es sehr kompliziert, da der Hierarchiebaum der ContextUnterklassen, abgesehen davon, dass er ein Gottobjekt ist, brutal gegen das Liskov-Substitutionsprinzip verstößt.

In diesem Blogbeitrag wird versucht, die ContextAnwendbarkeit von Klassen in verschiedenen Situationen zusammenzufassen.

Lassen Sie mich der Vollständigkeit halber die Haupttabelle aus diesem Beitrag kopieren:

+----------------------------+-------------+----------+---------+-----------------+-------------------+
|                            | Application | Activity | Service | ContentProvider | BroadcastReceiver |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
| Show a Dialog              | NO          | YES      | NO      | NO              | NO                |
| Start an Activity          | NO¹         | YES      | NO¹     | NO¹             | NO¹               |
| Layout Inflation           | NO²         | YES      | NO²     | NO²             | NO²               |
| Start a Service            | YES         | YES      | YES     | YES             | YES               |
| Bind to a Service          | YES         | YES      | YES     | YES             | NO                |
| Send a Broadcast           | YES         | YES      | YES     | YES             | YES               |
| Register BroadcastReceiver | YES         | YES      | YES     | YES             | NO³               |
| Load Resource Values       | YES         | YES      | YES     | YES             | YES               |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
  1. Eine Anwendung KANN von hier aus eine Aktivität starten, erfordert jedoch die Erstellung einer neuen Aufgabe. Dies passt möglicherweise zu bestimmten Anwendungsfällen, kann jedoch zu nicht standardmäßigen Backstack-Verhaltensweisen in Ihrer Anwendung führen und wird im Allgemeinen nicht empfohlen oder als bewährte Methode angesehen.
  2. Dies ist legal, aber die Inflation erfolgt mit dem Standardthema für das System, auf dem Sie ausgeführt werden, und nicht mit dem, was in Ihrer Anwendung definiert ist.
  3. Erlaubt, wenn der Empfänger null ist, was zum Abrufen des aktuellen Werts einer Sticky-Sendung unter Android 4.2 und höher verwendet wird.

Bildschirmfoto


Toller Blog-Beitrag, auf den du verlinkt hast!
Lejonl

28

Contextbietet Informationen über die ActvityoderApplication zu neu erstellten Komponenten.

ContextNeu erstellte Komponenten sollten relevant sein (egal ob Anwendungskontext oder Aktivitätskontext).

Da Activityes sich um eine Unterklasse von handelt Context, kann thisder Kontext dieser Aktivität abgerufen werden


Wo ist Ihre Erklärung zu baseContext?
IgorGanapolsky

1

Aus diesen Dokumenten

Ich habe verstanden, dass Sie verwenden sollten:

Versuchen Sie, die Kontextanwendung anstelle einer Kontextaktivität zu verwenden


0

getApplicationContext ()

Dies wird für die Anwendungsebene verwendet und bezieht sich auf alle Aktivitäten.

getContext () und getBaseContext ()

ist höchstwahrscheinlich gleich .dies werden nur aktuelle Aktivitäten angeboten, die live sind.

diese

verweist immer auf das aktuelle Klassenobjekt.


0

A Contextist:

  • Eine abstrakte Klasse, deren Implementierung vom Android-System bereitgestellt wird.
  • Es ermöglicht den Zugriff auf anwendungsspezifische Ressourcen und Klassen sowie das Aufrufen von Vorgängen auf Anwendungsebene wie das Starten von Aktivitäten, das Senden und Empfangen von Absichten usw.
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.