Stimmt in einer Android-App der folgende Ansatz nicht:
public class MyApp extends android.app.Application {
private static MyApp instance;
public MyApp() {
instance = this;
}
public static Context getContext() {
return instance;
}
}
und überall dort übergeben (zB SQLiteOpenHelper), wo Kontext benötigt wird (und natürlich nicht leckt)?
android
android-context
yanchenko
quelle
quelle
<application>
Um dies für andere zu erläutern, die dies implementieren, können Sie den Knoten Ihrer AndroidManifest.xml-Datei so ändern , dass er die folgende Attributdefinition enthält :android:name="MyApp"
. MyApp muss sich unter demselben Paket befinden, auf das Ihr Manifest verweist.Antworten:
Es gibt einige potenzielle Probleme mit diesem Ansatz, obwohl er unter vielen Umständen (wie in Ihrem Beispiel) gut funktioniert.
Insbesondere sollten Sie vorsichtig sein, wenn Sie mit etwas umgehen, das sich mit dem befasst
GUI
, was a erfordertContext
. Wenn Sie beispielsweise den Anwendungskontext an übergeben, erhaltenLayoutInflater
Sie eine Ausnahme. Im Allgemeinen ist Ihr Ansatz ausgezeichnet: Es ist empfehlenswert, einenActivity's
Context
innerhalb dieses Ansatzes zu verwendenActivity
undApplication Context
beim Übergeben eines Kontexts, der über den Rahmen eines hinausgehtActivity
, Speicherlecks zu vermeiden .Auch als Alternative zu Ihrem Muster können Sie die Verknüpfung von Aufrufen verwenden
getApplicationContext()
auf einemContext
Objekt (zB eine Aktivität) , um den Anwendungskontext zu erhalten.quelle
LayoutInflator
gerade für mich funktioniert. Muss in den letzten drei Jahren geändert worden sein.Nach meiner Erfahrung sollte dieser Ansatz nicht notwendig sein. Wenn Sie den Kontext für etwas benötigen, können Sie ihn normalerweise über einen Aufruf von View.getContext () abrufen. Mit dem dort
Context
erhaltenen können Sie Context.getApplicationContext () aufrufen , um denApplication
Kontext abzurufen . Wenn Sie versuchen, denApplication
Kontext von einemActivity
abzurufen, können Sie jederzeit Activity.getApplication () aufrufen , das alsContext
für einen Aufruf an übergeben werden sollteSQLiteOpenHelper()
.Insgesamt scheint es kein Problem mit Ihrem Ansatz für diese Situation zu geben, aber stellen Sie beim Umgang
Context
damit sicher, dass Sie nirgendwo Speicher verlieren, wie im offiziellen Blog von Google Android Developers beschrieben .quelle
Einige Leute haben gefragt: Wie kann der Singleton einen Nullzeiger zurückgeben? Ich beantworte diese Frage. (Ich kann nicht in einem Kommentar antworten, da ich eine Postleitzahl eingeben muss.)
Zwischen zwei Ereignissen kann null zurückgegeben werden: (1) die Klasse wird geladen und (2) das Objekt dieser Klasse wird erstellt. Hier ist ein Beispiel:
Lassen Sie uns den Code ausführen:
Die zweite Zeile zeigt , daß Y.xinstance und X.yinstance ist null ; sie sind null , weil die Variablen X.xinstance ans Y.yinstance gelesen wurden , wenn sie null waren.
Kann das behoben werden? Ja,
und dieser Code zeigt keine Anomalie:
ABER dies ist keine Option für das Android-
Application
Objekt: Der Programmierer steuert nicht die Zeit, zu der es erstellt wird.Noch einmal: Der Unterschied zwischen dem ersten und dem zweiten Beispiel besteht darin, dass das zweite Beispiel eine Instanz erstellt, wenn der statische Zeiger null ist. Ein Programmierer kann das Android-Anwendungsobjekt jedoch nicht erstellen, bevor sich das System dafür entscheidet.
AKTUALISIEREN
Ein weiteres rätselhaftes Beispiel, in dem sich initialisierte statische Felder befinden
null
.Main.java :
Und du bekommst:
Beachten Sie, dass Sie die statische Variablendeklaration nicht um eine Zeile nach oben verschieben können. Der Code wird nicht kompiliert.
quelle
Anwendungsklasse:
Deklarieren Sie die Anwendung im AndroidManifest:
Verwendungszweck:
quelle
Sie versuchen, einen Wrapper zu erstellen, um den Anwendungskontext abzurufen, und es besteht die Möglichkeit, dass er den
null
Zeiger " " zurückgibt.Nach meinem Verständnis denke ich, dass es besser ist, eine der 2
Context.getApplicationContext()
oder 2 anzurufenActivity.getApplication()
.quelle
Es ist ein guter Ansatz. Ich benutze es auch selbst. Ich würde nur vorschlagen, zu überschreiben
onCreate
, um den Singleton festzulegen, anstatt einen Konstruktor zu verwenden.Und da haben Sie schon erwähnt
SQLiteOpenHelper
: In könnenonCreate ()
Sie auch die Datenbank öffnen.Persönlich denke ich, dass die Dokumentation falsch war, als sie sagte, dass es normalerweise nicht notwendig ist, die Anwendung in eine Unterklasse zu unterteilen . Ich denke, das Gegenteil ist der Fall: Sie sollten Application immer unterordnen.
quelle
Ich würde den Anwendungskontext verwenden, um einen Systemdienst im Konstruktor abzurufen. Dies erleichtert das Testen und profitiert von der Zusammensetzung
Die Testklasse würde dann den überladenen Konstruktor verwenden.
Android würde den Standardkonstruktor verwenden.
quelle
Ich mag es, aber ich würde stattdessen einen Singleton vorschlagen:
quelle
new
die Anwendung niemals selbst erstellen (mit der möglichen Ausnahme von Unit-Tests). Das Betriebssystem wird das tun. Sie sollten auch keinen Konstruktor haben. Dafür ist daonCreate
.Ich benutze den gleichen Ansatz, ich schlage vor, den Singleton etwas besser zu schreiben:
aber ich benutze nicht überall, ich benutze
getContext()
undgetApplicationContext()
wo ich es tun kann!quelle