Gibt es eine Möglichkeit, die aktuelle Context
Instanz in eine statische Methode zu integrieren?
Ich suche nach diesem Weg, weil ich es hasse, die 'Context'-Instanz jedes Mal zu speichern, wenn sie sich ändert.
android
android-context
Andrea Baccega
quelle
quelle
Context
, gibt es möglicherweise eine bessere Methode zum Entwerfen des Codes.Antworten:
Mach das:
Deklarieren Sie in der Android Manifest-Datei Folgendes.
Dann schreibe die Klasse:
Rufen
MyApplication.getAppContext()
Sie jetzt überall an, um Ihren Anwendungskontext statisch abzurufen.quelle
static context
Variable auch als deklarierenvolatile
?Die meisten Apps, die eine bequeme Methode zum Abrufen des Anwendungskontexts wünschen, erstellen eine eigene Klasse, die erweitert wird
android.app.Application
.LEITEN
Sie können dies erreichen, indem Sie zuerst eine Klasse in Ihrem Projekt wie folgt erstellen:
Dann sollten Sie in Ihrem AndroidManifest den Namen Ihrer Klasse im Tag von AndroidManifest.xml angeben:
Anschließend können Sie den Anwendungskontext in einer beliebigen statischen Methode wie folgt abrufen:
WARNUNG
Bevor Sie Ihrem Projekt etwas Ähnliches hinzufügen, sollten Sie überlegen, was in der Dokumentation steht:
BETRACHTUNG
Es gibt auch eine andere Möglichkeit, den Anwendungskontext mithilfe von Reflection abzurufen. Reflexion wird in Android oft herabgesetzt und ich persönlich denke, dass dies nicht in der Produktion verwendet werden sollte.
Um den Anwendungskontext abzurufen, müssen wir eine Methode für eine versteckte Klasse ( ActivityThread ) aufrufen, die seit API 1 verfügbar ist:
Es gibt noch eine versteckte Klasse ( AppGlobals ), mit der der Anwendungskontext statisch abgerufen werden kann. Der Kontext wird verwendet,
ActivityThread
sodass es wirklich keinen Unterschied zwischen der folgenden und der oben angegebenen Methode gibt:Viel Spaß beim Codieren!
quelle
Angenommen, wir sprechen über das Abrufen des Anwendungskontexts, habe ich ihn implementiert, wie von @Rohit Ghatol vorgeschlagen. Was dann passiert ist, ist, dass es keine Garantie dafür gibt, dass der so abgerufene Kontext immer nicht null ist. Zu dem Zeitpunkt, an dem Sie es benötigen, können Sie normalerweise nicht verzögern, weil Sie einen Helfer initialisieren oder eine Ressource abrufen möchten. Die Behandlung des Nullfalls hilft Ihnen nicht weiter. Ich habe also verstanden, dass ich im Grunde gegen die Android-Architektur gekämpft habe, wie in den Dokumenten angegeben
und erklärt von Dianne Hackborn
Sie schlägt auch die Lösung für dieses Problem vor:
Ich habe also die Erweiterung von Application entfernt und den Kontext direkt an getInstance () des Singleton-Helfers übergeben, während ich einen Verweis auf den Anwendungskontext im privaten Konstruktor gespeichert habe:
Der Anrufer übergibt dann einen lokalen Kontext an den Helfer:
Um diese Frage richtig zu beantworten: Es gibt Möglichkeiten, statisch auf den Anwendungskontext zuzugreifen, aber alle sollten entmutigt werden, und Sie sollten es vorziehen, einen lokalen Kontext an getInstance () des Singletons zu übergeben.
Für alle Interessierten können Sie eine ausführlichere Version im fwd-Blog lesen
quelle
getInstance(ctx)
. Sie haben einen GC-Stamminstance
vom TypMyHelper
, der ein privates FeldmContext
vom Typ hatContext
, das auf den Anwendungskontext verweist, der über den an übergebenen Kontext gesammelt wurdegetInstance()
.instance
wird niemals ein zweites Mal festgelegt oder gelöscht, sodass GC niemals den App-Kontext abfängt, auf den verwiesen wirdinstance
. Sie verlieren keine Aktivitäten, so dass es IMO kostengünstig ist.this
in veröffentlichenApplication.onCreate()
, wodurch die akzeptierte Antwort besser wird.Nein, ich glaube nicht. Leider können Sie nicht mehr
getApplicationContext()
vonActivity
oder einer der anderen Unterklassen von anrufenContext
. Auch diese Frage ist etwas verwandt.quelle
Hier ist eine undokumentierte Möglichkeit, eine Anwendung (die ein Kontext ist) von einer beliebigen Stelle im UI-Thread abzurufen. Es basiert auf der versteckten statischen Methode
ActivityThread.currentApplication()
. Es sollte mindestens unter Android 4.x funktionieren.Beachten Sie, dass diese Methode möglicherweise null zurückgibt, z. B. wenn Sie die Methode außerhalb des UI-Threads aufrufen oder die Anwendung nicht an den Thread gebunden ist.
Es ist immer noch besser, die Lösung von @RohitGhatol zu verwenden , wenn Sie den Anwendungscode ändern können.
quelle
Es hängt davon ab, wofür Sie den Kontext verwenden. Ich kann mir mindestens einen Nachteil dieser Methode vorstellen:
Wenn Sie versuchen, ein
AlertDialog
mit zu erstellenAlertDialog.Builder
,Application
funktioniert der Kontext nicht. Ich glaube, Sie brauchen den Kontext für die aktuelleActivity
...quelle
Kotlin Weg :
Manifest:
MyApplication.kt
Sie können dann über auf die Unterkunft zugreifen
MyApplication.instance
quelle
Wenn Sie RoboGuice verwenden möchten , können Sie den Kontext in jede gewünschte Klasse einfügen . Hier ist ein kleines Beispiel, wie es mit RoboGuice 2.0 (Beta 4 zum Zeitpunkt dieses Schreibens) gemacht wird.
quelle
Ich habe das irgendwann benutzt:
Dies ist ein gültiger Kontext, den ich beim Abrufen von Systemdiensten und beim Arbeiten verwendet habe.
Aber ich habe es nur in Framework- / Basismodifikationen verwendet und es nicht in Android-Anwendungen ausprobiert.
Eine Warnung , die Sie wissen müssen: Wenn Sie sich für Rundfunkempfänger in diesem Kontext registrieren, funktioniert dies nicht und Sie erhalten:
quelle
Kotlin
und Kontext wie bekommen
oder
quelle
Sie können Folgendes verwenden:
MainActivity.java:
Jede andere Klasse:
quelle
Wenn Sie die Manifestdatei nicht ändern möchten, können Sie den Kontext in Ihrer anfänglichen Aktivität manuell in einer statischen Variablen speichern:
Und legen Sie einfach den Kontext fest, wenn Ihre Aktivität (oder Aktivitäten) beginnen:
Hinweis: Wie bei allen anderen Antworten handelt es sich um einen potenziellen Speicherverlust.
quelle
Ich denke, Sie brauchen einen Körper für die
getAppContext()
Methode:quelle
Laut dieser Quelle können Sie Ihren eigenen Kontext erhalten, indem Sie ContextWrapper erweitern
JavaDoc für ContextWrapper
quelle
Wenn Sie aus irgendeinem Grund einen Anwendungskontext in einer Klasse wünschen, nicht nur in solchen, die die Anwendung / Aktivität erweitern, möglicherweise für einige Factory- oder Hilfsklassen. Sie können Ihrer App den folgenden Singleton hinzufügen.
Initialisieren Sie es dann in onCreate Ihrer Anwendungsklasse mit
Verwenden Sie es überall, indem Sie anrufen
Ich empfehle diesen Ansatz jedoch nur für den Anwendungskontext. Da es zu Speicherlecks kommen kann.
quelle
Ich verwende eine Variation des Singleton-Entwurfsmusters, um mir dabei zu helfen.
Ich rufe dann
ApplicationContextSingleton.setContext( this );
in meinem activity.onCreate () undApplicationContextSingleton.setContext( null );
in onDestroy () ;quelle
Ich habe gerade ein von jQuery inspiriertes Framework für Android namens Vapor API veröffentlicht , das die App-Entwicklung vereinfachen soll.
Die zentrale
$
Fassadenklasse verwaltet einenWeakReference
(Link zu einem großartigen Java-Blog-Beitrag von Ethan Nicholas) zum aktuellenActivity
Kontext, den Sie abrufen können, indem Sie Folgendes aufrufen:EIN
WeakReference
verwaltet eine Referenz, ohne zu verhindern, dass die Garbage Collection das ursprüngliche Objekt zurückfordert, sodass Sie kein Problem mit Speicherlecks haben sollten.Der Nachteil ist natürlich, dass Sie das Risiko
$.act()
eingehen, null zurückzugeben. Ich bin jedoch noch nicht auf dieses Szenario gestoßen, daher ist es vielleicht nur ein minimales Risiko, das es wert ist, erwähnt zu werden.Sie können den Kontext auch manuell festlegen, wenn Sie ihn nicht verwenden
VaporActivity
alsActivity
Klasse verwenden:Auch ein Großteil der Vapor-API- Frameworks diesen gespeicherten Kontext von Natur aus, was bedeuten kann, dass Sie ihn überhaupt nicht selbst speichern müssen, wenn Sie sich für die Verwendung des Frameworks entscheiden. Schauen Sie sich die Website anWeitere Informationen und Beispiele finden .
Ich hoffe das hilft :)
quelle
Rohits Antwort scheint richtig zu sein. Beachten Sie jedoch, dass AndroidStudios "Instant Run" meines Wissens davon abhängt, dass
static Context
Ihr Code keine Attribute enthält.quelle
Wenn Sie in Kotlin Context / App Context in das Begleitobjekt einfügen, wird weiterhin eine Warnung ausgegeben
Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
oder wenn Sie so etwas verwenden:
Es täuscht nur die Flusen, den Speicherverlust nicht zu entdecken. Die App-Instanz kann immer noch einen Speicherverlust erzeugen, da die Anwendungsklasse und ihr Nachkomme ein Kontext sind.
Alternativ können Sie eine funktionale Schnittstelle oder funktionale Eigenschaften verwenden, um Ihren App-Kontext abzurufen.
Erstellen Sie einfach eine Objektklasse:
oder Sie könnten es sicherer verwenden, indem Sie den Typ nullable verwenden:
und fügen Sie in Ihrer App-Klasse diese Zeile hinzu:
und deklarieren Sie in Ihrem Manifest den App-Namen zu
. MyApp
Wenn Sie den Kontext erhalten möchten, rufen Sie einfach an:
Hoffe es wird helfen.
quelle
Versuchen Sie so etwas
quelle