449 Stimmen

getApplication() vs. getApplicationContext()

Ich konnte keine befriedigende Antwort auf diese Frage finden, also hier ist sie: Was hat es mit Activity/Service.getApplication() y Context.getApplicationContext() ?

In unserer Anwendung geben beide das gleiche Objekt zurück. In einer ActivityTestCase Wenn Sie die Anwendung jedoch nachahmen, wird die getApplication() mit dem Spott zurückkommen, aber getApplicationContext gibt immer noch eine andere Kontextinstanz zurück (eine, die von Android injiziert wurde). Ist das ein Fehler? Ist es beabsichtigt?

Ich verstehe den Unterschied überhaupt nicht. Gibt es Fälle außerhalb einer Testsuite, in denen beide Aufrufe mit unterschiedlichen Objekten zurückkommen können? Wann und warum? Außerdem, warum ist getApplication festgelegt am Activity y Service , aber nicht auf Context ? Sollte nicht immer eine gültige Anwendungsinstanz verfügbar sein von überall ?

392voto

Pierre-Yves Ricau Punkte 7926

Eine sehr interessante Frage. Ich denke, es handelt sich hauptsächlich um eine semantische Bedeutung, die auch historisch bedingt sein kann.

Obwohl in aktuellen Android-Activity- und Service-Implementierungen, getApplication() y getApplicationContext() dasselbe Objekt zurückgeben, gibt es keine Garantie dafür, dass dies immer der Fall ist (z. B. bei einer bestimmten Herstellerimplementierung).

Wenn Sie also die Anwendungsklasse, die Sie im Manifest registriert haben, haben möchten, sollten Sie niemals aufrufen getApplicationContext() und übertragen Sie es auf Ihre Anwendung, da es sich möglicherweise nicht um die Anwendungsinstanz handelt (was Sie offensichtlich mit dem Test-Framework erfahren haben).

Warum ist getApplicationContext() überhaupt existieren?

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

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

Wenn Sie sich den Android-Code ansehen, sehen Sie, dass eine Aktivität, wenn sie angehängt wird, einen Basiskontext und eine Anwendung erhält, und das sind unterschiedliche Parameter. getApplicationContext() delegiert seine Aufforderung an baseContext.getApplicationContext() .

Und noch etwas: In der Dokumentation steht, dass Sie in den meisten Fällen keine Unterklasse Application benötigen:

Normalerweise ist es nicht notwendig, die Unterklasse Application . In den meisten Fällen, können statische Singletons die gleiche Funktionalität auf modularere Weise Weise bereitstellen. Wenn Ihr Singleton einen globalen Kontext benötigt (z.B. zur Registrierung von Broadcast-Empfänger), kann die Funktion, die ihn abruft, mit einem Context die intern die Context.getApplicationContext() wenn der ersten Konstruktion des Singletons.

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

33voto

usethe4ce Punkte 22481

Es scheint mit dem Kontextumbruch zu tun zu haben. Die meisten Klassen, die von Context sind eigentlich ein ContextWrapper die im Wesentlichen an einen anderen Kontext delegiert, möglicherweise mit Änderungen durch den Wrapper.

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

Aktivitäten und Dienstleistungen sind spezifischer mit einem Application Objekt. Der Nutzen hiervon liegt meines Erachtens darin, dass Sie eine benutzerdefinierte Klasse erstellen und im Manifest registrieren können, die von Application und sicher sein, dass Activity.getApplication() o Service.getApplication() gibt dieses spezifische Objekt dieses spezifischen Typs zurück, das Sie in Ihr abgeleitetes Application Klasse und verwenden Sie sie für beliebige Zwecke.

Mit anderen Worten, getApplication() wird garantiert ein Application Objekt, während getApplicationContext() steht es frei, stattdessen einen Proxy zurückzugeben.

30voto

RivieraKid Punkte 5903

Vergleichen Sie [getApplication()](http://developer.android.com/reference/android/app/Activity.html#getApplication()) y [getApplicationContext()](http://developer.android.com/reference/android/content/Context.html#getApplicationContext()) .

getApplication gibt eine Application Objekt, mit dem Sie Ihren globalen Anwendungsstatus verwalten und auf einige Gerätesituationen reagieren können, wie z. B. [onLowMemory()](http://developer.android.com/reference/android/app/Application.html#onLowMemory()) y onConfigurationChanged() .

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) werden kann, wenn Ihre Aktivität endet. Der Anwendungskontext bleibt verfügbar, solange Ihr Anwendungsobjekt existiert (das nicht an ein bestimmtes Objekt gebunden ist). Activity ), so dass Sie dies für Dinge verwenden können wie Benachrichtigungen die einen Kontext benötigen, der über längere Zeiträume und unabhängig von flüchtigen UI-Objekten verfügbar ist.

Ich schätze, es hängt davon ab, was Ihr Code tut, ob diese gleich sein können oder nicht - obwohl ich bei normalem Gebrauch erwarten würde, dass sie unterschiedlich sind.

-13voto

Lenny Porter Punkte 15

Um die Frage zu beantworten: getApplication() gibt ein Application-Objekt zurück, und getApplicationContext() gibt ein Context-Objekt zurück. Aufgrund Ihrer eigenen Beobachtungen würde ich davon ausgehen, dass der Context beider identisch ist (d.h. hinter den Kulissen ruft die Anwendungsklasse die letztgenannte Funktion auf, um den Context-Teil der Basisklasse aufzufüllen, oder es findet eine gleichwertige Aktion statt). Es sollte eigentlich egal sein, welche Funktion Sie aufrufen, wenn Sie nur einen Context benötigen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X