wake-up-neo.com

getApplication () vs. getApplicationContext ()

Darauf konnte ich keine zufriedenstellende Antwort finden. Also los geht's: Was ist mit Activity/Service.getApplication() und Context.getApplicationContext()?

In unserer Anwendung geben beide dasselbe Objekt zurück. In einem ActivityTestCase führt das Verspotten der Anwendung jedoch dazu, dass getApplication() mit dem Verspotten zurückkommt, aber getApplicationContext gibt immer noch eine andere Kontextinstanz zurück (eine, die von Android injiziert wurde). Ist das ein Bug? Ist es absichtlich?

Ich verstehe den Unterschied überhaupt nicht. Gibt es Fälle außerhalb einer Testsuite, in denen beide Aufrufe möglicherweise mit unterschiedlichen Objekten zurückkommen? Wann und warum? Warum ist getApplication für Activity und Service definiert, nicht jedoch für Context? Sollte es nicht immer eine gültige Anwendungsinstanz von irgendwo geben?

401
Matthias

Sehr interessante Frage. Ich denke, es ist hauptsächlich eine semantische Bedeutung und kann auch historische Gründe haben.

Obwohl in aktuellen Android Aktivitäts- und Dienstimplementierungen getApplication() und getApplicationContext() dasselbe Objekt zurückgeben, kann nicht garantiert werden, dass dies immer der Fall ist (z. B. bei einem bestimmten Anbieter) Implementierung).

Wenn Sie also die Anwendungsklasse haben möchten, die Sie im Manifest registriert haben, sollten Sie niegetApplicationContext() aufrufen und sie in Ihre Anwendung umwandeln, da es sich möglicherweise nicht um die Anwendungsinstanz handelt (mit der Sie offensichtlich Erfahrungen gemacht haben) das Test-Framework).

Warum existiert getApplicationContext() überhaupt?

getApplication() ist nur in der Activity-Klasse und der Service-Klasse verfügbar, während getApplicationContext() in der Context-Klasse deklariert ist.

Das bedeutet eigentlich eines: Wenn Sie Code in einen Rundfunkempfänger schreiben, der kein Kontext ist, sondern in seiner onReceive-Methode einen Kontext erhält, können Sie nur getApplicationContext() aufrufen. Dies bedeutet auch, dass Sie nicht garantiert auf Ihre Anwendung in einem BroadcastReceiver zugreifen können.

Wenn Sie sich den Android -Code ansehen, sehen Sie, dass eine Aktivität im angehängten Zustand einen Basiskontext und eine Anwendung erhält. Dies sind unterschiedliche Parameter. getApplicationContext() delegiert den Aufruf an baseContext.getApplicationContext().

Eine weitere Sache: Die Dokumentation besagt, dass Sie in den meisten Fällen keine Unterklasse für Application benötigen sollten:

Normalerweise ist es nicht erforderlich, Application zu unterteilen. In den meisten Fällen können statische Singletons die gleiche Funktionalität modularer bereitstellen. Wenn Ihr Singleton einen globalen Kontext benötigt (zum Beispiel zum Registrieren von Rundfunkempfängern), kann der Funktion zum Abrufen ein Context zugewiesen werden, das beim erstmaligen Erstellen des Singleton intern Context.getApplicationContext() verwendet.

Ich weiß, dass dies keine exakte und präzise Antwort ist, aber beantwortet das trotzdem Ihre Frage?

356

Vergleiche getApplication() und getApplicationContext() .

getApplication gibt ein Application -Objekt zurück, mit dem Sie Ihren globalen Anwendungsstatus verwalten und auf bestimmte Gerätesituationen wie onLowMemory() und onConfigurationChanged() reagieren können.

getApplicationContext gibt den globalen Anwendungskontext zurück. Der Unterschied zu anderen Kontexten besteht darin, dass beispielsweise ein Aktivitätskontext von Android zerstört (oder anderweitig nicht verfügbar gemacht) wird, wenn Ihre Aktivität endet. Der Anwendungskontext bleibt solange verfügbar, wie Ihr Anwendungsobjekt vorhanden ist (das nicht an einen bestimmten Activity gebunden ist), sodass Sie diesen für Dinge wie Benachrichtigungen verwenden können, die einen Kontext erfordern, der für längere Zeiträume und verfügbar ist unabhängig von transienten UI-Objekten.

Ich denke, es hängt davon ab, was Ihr Code tut, ob diese gleich sind oder nicht - obwohl ich bei normaler Verwendung davon ausgehen würde, dass sie unterschiedlich sind.

31
RivieraKid

Es scheint mit Context Wrapping zu tun zu haben. Die meisten von Context abgeleiteten Klassen sind tatsächlich ContextWrapper , die im Wesentlichen an einen anderen Kontext delegieren, möglicherweise mit Änderungen durch den Wrapper.

Der Kontext ist eine allgemeine Abstraktion, die das Verspotten und Proxying unterstützt. Da viele Kontexte an ein Objekt mit begrenzter Lebensdauer gebunden sind, wie z. B. Activity , muss es eine Möglichkeit geben, einen längerlebigen Kontext zu erhalten, z. B. um sich für zukünftige Benachrichtigungen zu registrieren. Dies wird erreicht durch Context.getApplicationContext() . Eine logische Implementierung besteht darin, das globale Objekt Application zurückzugeben, aber nichts hindert eine Kontextimplementierung daran, stattdessen einen Wrapper oder Proxy mit einer geeigneten Lebensdauer zurückzugeben.

Aktivitäten und Services sind insbesondere mit einem Application -Objekt verknüpft. Ich glaube, Sie können eine benutzerdefinierte Klasse erstellen und im Manifest registrieren, die von Application abgeleitet ist, und Sie können sicher sein, dass Activity.getApplication() oder Service.getApplication() dieses bestimmte Objekt zurückgibt von diesem spezifischen Typ, den Sie in Ihre abgeleitete Klasse Application umwandeln und für jeden benutzerdefinierten Zweck verwenden können.

Mit anderen Worten, getApplication() gibt garantiert ein Application-Objekt zurück, während getApplicationContext() stattdessen einen Proxy zurückgeben kann.

29
usethe4ce