Android: Statische Variable null bei wenig Speicher
Lesezeit: 7 Minuten
MathieuC
Ich habe eine Anwendung, die einige statische Variablen hat. Diese Variablen werden in einer unabhängigen Klasse namens DataContext gespeichert. Diese Variablen werden beim Anwendungsstart aus Rohdateien initialisiert (eine Methode namens DataContext.initConstant() wird in onCreate() von MyApplication aufgerufen, die Application erweitert).
(BEARBEITEN: Die initConstant-Methode verwendet eine AsyncTask, um diese Daten aus Dateien zu laden).
Wenn meine Anwendung für eine bestimmte Zeit in den Hintergrund tritt oder wenn meine Anwendung zu viel Speicher verbraucht hat, werden diese statischen Variablen null.
Wie kann es verhindert werden?
Wenn nicht, was soll ich mit meinen statischen Variablen machen?
Ich habe andere Daten, die in statischen Variablen gespeichert sind, die für verschiedene Aktivitäten verwendet werden sollen, aber ich lösche sie oder übergebe sie an null in der onLowMemory() von MyApplication.
Was ist der beste Weg, um einige Daten zwischen Aktivitäten zugänglich zu halten, wenn diese Daten zu groß sind, um in einem Intent serialisiert zu werden, eine Datenbank nicht verwendet werden kann (aus welchen Gründen auch immer) und auch nicht durch Serialisierung in Dateien gespeichert werden können?
Können Sie erläutern, warum Datenbanken oder serialisierte Dateien nicht funktionieren würden?
– sarga
25. Januar 2011 um 18:29 Uhr
Ich habe viele Informationen und ändere jetzt die Art und Weise, wie ich darauf zugreife, weil ich wenig Zeit habe und wir nur das Problem herausfinden.
– MathieuC
26. Januar 2011 um 9:38 Uhr
@MathieuC: Bitte teilen Sie die Lösung, ich stehe auch seit sehr langer Zeit vor dem gleichen Problem.
– Sagar Panwala
16. Februar 2016 um 7:19 Uhr
Du kannst nicht. Android muss von Zeit zu Zeit Speicherplatz freigeben. Stellen Sie sich vor, alle Anwendungen hätten eine Menge statischer Daten, die für immer resident sein sollen – wie würden Sie das in den Arbeitsspeicher einpassen? Es ist ein Mobiltelefon. Es hat keinen virtuellen Speicher.
(und 3): Alles, was persistent sein soll, muss gespeichert werden, entweder über SharedPreferences, eine Sqlite-Datenbank oder eine Datei.
Ok danke, aber ich kann die Art und Weise, wie meine App jetzt funktioniert, nicht ändern. Aber ich werde es auf jeden Fall ändern, wenn ich könnte.
– MathieuC
26. Januar 2011 um 9:35 Uhr
Höchstwahrscheinlich besteht das Problem darin, dass Ihre Anwendung beendet wird, während sie sich im Hintergrund befindet, und dann neu erstellt wird, wenn Sie darauf zurückkommen. Probier das aus Aktivitätslebenszyklus Dokumentation darüber, wann dies für eine einzelne Aktivität auftreten könnte. Sie müssen sicherstellen, dass Sie alles, was im Speicher gespeichert ist, zum richtigen Zeitpunkt in einen dauerhafteren Speicher verschieben, um zu vermeiden, dass diese Informationen verloren gehen, wenn die App beendet wird.
Ich bin mir nicht sicher, was genau Sie speichern, aber es hört sich so an, als ob die Verwendung von Shared Preferences gut funktionieren könnte. Diese Seite auf Datenspeicher erläutert eine Reihe verschiedener Möglichkeiten, Daten dauerhafter zu speichern, einschließlich gemeinsamer Einstellungen.
Die Anwendung wird nicht beendet, da in diesem Fall meine statische Variable neu erstellt würde, denn wenn die Anwendung zerstört wird, würde die Methode onCreate() von MyApplication aufgerufen, wenn sie neu erstellt wird.
– MathieuC
25. Januar 2011 um 18:33 Uhr
Wenn Sie keine Rohdateien verwenden, würde ich empfehlen, die Klasse zu initialisieren, wenn sie geladen wird.
Zum Beispiel,
public static Map<?,?> myStaticMap = new HashMap<?,?>();
static { //fill myStaticMap }
Sie haben einige größere Bedenken, um die Sie sich Sorgen machen müssen, wenn Sie Dateien auf diese Weise laden. Was ist zum Beispiel mit E/A-Fehlern oder Latenzproblemen? Sie erhalten Warnungen in Lebkuchen (wenn Sie sie aktivieren), wenn Sie E/A in Ihrem Haupt-Thread ausführen. Vielleicht sollten Sie anstelle einer Klasse mit statischen Feldern ein Objekt haben, um diese Werte abzurufen. (vielleicht mit einem statischen Cache, obwohl Sie darauf synchronisieren sollten, bevor Sie ihn überprüfen / ändern)
Keine Sorge, mein Laden befindet sich nicht im Hauptthread (ich verwende eine AsyncTask, um die Arbeit in meiner initConstant-Methode zu erledigen.
– MathieuC
25. Januar 2011 um 18:34 Uhr
Wenn DataContext.initConstant() in einer AsyncTask aufgerufen wird und Ihre Anwendung zerstört und vom System neu gestartet wird, gibt es eine Zeit zwischen der Erstellung Ihrer Aktivität und dem erwarteten Füllen von DataContext und dem Zeitpunkt, zu dem es tatsächlich gefüllt wird. Dies ist möglicherweise der Grund, warum Sie festgestellt haben, dass es null ist – es wurde noch nicht neu erstellt, aber einige Ihrer Aktivitäten erwarten, dass es zum Zeitpunkt ihrer Ausführung vollständig initialisiert ist.
– Kai
16. Juli 2013 um 4:03 Uhr
Ich nehme an, dass dies ein Daten-Cache-Problem ist.
Es ist nicht garantiert, dass das Speichern von Daten in der statischen Klasse funktioniert, wenn Benutzer häufig Apps wechseln. Das Android-System fordert alle Hintergrundaktivitäten zurück, wenn der Speicher niedrig ist. Statische Klasse gehört definitiv zu dieser Kategorie.
Der richtige Weg, dies zu tun, ist die Verwendung SharedPreference um Cache-Daten zu persistieren.
Sie können Ihren eigenen Getter und Setter der gewünschten Daten erstellen und ihn um das sharedPreference-Objekt wickeln. Beim Zugriff per Getter sollten Sie immer prüfen, ob der Wert leer oder abgelaufen ist. Sie können eine speichern update_time bei der Verwendung von Setter.
Für aktivitätsspezifische Daten können Sie einfach verwenden getPreference(permission)wenn Sie Daten über Aktivitäten und andere Anwendungskomponenten hinweg teilen möchten, können Sie verwenden getSharedPreference(name, permission).
Normalerweise ist die Berechtigung MODE_PRIVATE, sodass auf die Daten nur innerhalb Ihrer Anwendung zugegriffen werden kann.
Sie sollten Daten gruppieren und im unterschiedlichen sharedPreference-Objekt speichern. Dies ist eine bewährte Vorgehensweise, denn wenn Sie diese Gruppe von Daten für ungültig erklären möchten, ist es nur eine Frage eines Liners.
editor.clear(); editor.commit()
Wenn Sie ein komplexes Objekt zwischenspeichern möchten, sollten Sie es serialisieren. Ich bevorzuge das JSON-Format. Sie brauchen also einen Konvertierungsmechanismus. Dazu erstelle ich meine Datenobjektklasse, die die JSONable-Klasse erweitert. JSONable-Klasse haben toJSON() Methode u readFromJSON(). Dies ist praktisch, wenn Sie Daten wiederherstellen und serialisieren.
Amir Raminfar
Ich speichere a User Objekt und a Client Objekt in meinem statischen Bereich. Ich habe von Zeit zu Zeit bemerkt, dass die Referenz null wird. Also überprüfe ich jetzt in meinen Gettern, ob dieser Wert null ist, und wenn ja, starte ich die App neu.
Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
Ich hätte mich auch dafür entscheiden können, den Client neu zu laden, weil ich das Zugriffstoken in den Einstellungen speichere, aber ich mache so viele Initialisierungen, dass ich entschied, dass ein Neustart der App die beste Idee wäre.
Danke, aber das heißt, wenn der Benutzer ein sehr altes Gerät hat, könnte die Anwendung sehr oft neu gestartet werden, oder?
– MathieuC
26. Januar 2011 um 9:39 Uhr
Hm nicht genau. Ich habe die statischen Variablen tatsächlich in die Application-Klasse meiner Android-App eingefügt. Diese Variablen werden fast nie null, es sei denn, die gesamte App wird entfernt. Mir ist aufgefallen, dass diese nur dann null werden, wenn jemand Task Killer verwendet, um die App zu stoppen, aber die aktuelle Aktivität noch aktiv ist. Deshalb denke ich, dass dies eine so seltene Gelegenheit ist, dass ich die App einfach neu starten werde.
– Amir Raminfar
26. Januar 2011 um 14:06 Uhr
cjk
In deiner onResume() Methode könnten Sie die statischen Daten abfragen, um zu sehen, ob sie vorhanden sind, und wenn nicht, laden Sie sie erneut ein.
Danke, aber das heißt, wenn der Benutzer ein sehr altes Gerät hat, könnte die Anwendung sehr oft neu gestartet werden, oder?
– MathieuC
26. Januar 2011 um 9:39 Uhr
Hm nicht genau. Ich habe die statischen Variablen tatsächlich in die Application-Klasse meiner Android-App eingefügt. Diese Variablen werden fast nie null, es sei denn, die gesamte App wird entfernt. Mir ist aufgefallen, dass diese nur dann null werden, wenn jemand Task Killer verwendet, um die App zu stoppen, aber die aktuelle Aktivität noch aktiv ist. Deshalb denke ich, dass dies eine so seltene Gelegenheit ist, dass ich die App einfach neu starten werde.
– Amir Raminfar
26. Januar 2011 um 14:06 Uhr
Roban Ponraj A
Anstatt die statische Variable zu verwenden, können Sie die gemeinsame Präferenz zum Speichern des Werts verwenden.
Hinweis: Bei gemeinsamer Präferenz sollten Sie auch keine schwere Last geben.
Ich habe dieses Problem gelöst, indem ich die Superklasse mit Getter- und Setter-Funktion zum Speichern und Abrufen gemeinsam genutzter Präferenzvariablen habe.
Alle Klassen in meiner Anwendung erweiterten die Superklasse anstelle von Aktivität.
8350900cookie-checkAndroid: Statische Variable null bei wenig Speicheryes
Können Sie erläutern, warum Datenbanken oder serialisierte Dateien nicht funktionieren würden?
– sarga
25. Januar 2011 um 18:29 Uhr
Ich habe viele Informationen und ändere jetzt die Art und Weise, wie ich darauf zugreife, weil ich wenig Zeit habe und wir nur das Problem herausfinden.
– MathieuC
26. Januar 2011 um 9:38 Uhr
@MathieuC: Bitte teilen Sie die Lösung, ich stehe auch seit sehr langer Zeit vor dem gleichen Problem.
– Sagar Panwala
16. Februar 2016 um 7:19 Uhr