Ich habe eine Aktivität, die die Hauptaktivität ist, die in der App verwendet wird, und sie hat eine Reihe von Variablen. Ich habe zwei weitere Aktivitäten, bei denen ich die Daten der ersten Aktivität verwenden möchte. Jetzt weiß ich, dass ich so etwas tun kann:
GlobalState gs = (GlobalState) getApplication();
String s = gs.getTestMe();
Ich möchte jedoch viele Variablen gemeinsam nutzen und einige sind möglicherweise ziemlich groß, sodass ich keine Kopien wie oben erstellen möchte.
Gibt es eine Möglichkeit, die Variablen direkt abzurufen und zu ändern, ohne die Methoden get und set zu verwenden? Ich erinnere mich, dass ich in einem Artikel auf der Google Dev-Website gelesen habe, dass dies für die Leistung unter Android nicht empfohlen wird.
Antworten:
Hier eine Zusammenstellung der gängigsten Möglichkeiten, um dies zu erreichen :
WeakReferences
TL; DR : Es gibt zwei Möglichkeiten, Daten gemeinsam zu nutzen: Daten in den Extras der Absicht übergeben oder an einem anderen Ort speichern. Wenn es sich bei Daten um Grundelemente, Zeichenfolgen oder benutzerdefinierte Objekte handelt: Senden Sie sie als Teil der Absichts-Extras (benutzerdefinierte Objekte müssen implementiert werden
Parcelable
). Wenn Sie komplexe Objekte übergeben, speichern Sie eine Instanz in einem Singleton an einem anderen Ort und greifen Sie über die gestartete Aktivität darauf zu.Einige Beispiele, wie und warum jeder Ansatz implementiert werden soll:
Senden Sie Daten innerhalb von Absichten
Zur zweiten Aktivität:
Verwenden Sie diese Methode, wenn Sie primitive Daten oder Strings übergeben . Sie können auch Objekte übergeben, die implementiert werden
Serializable
.Obwohl verlockend, sollten Sie vor der Verwendung zweimal überlegen
Serializable
: Es ist fehleranfällig und schrecklich langsam. Also generell: meideSerializable
wenn möglich. Wenn Sie komplexe benutzerdefinierte Objekte übergeben möchten, sehen Sie sich dieParcelable
Benutzeroberfläche an . Es ist schwieriger zu implementieren, hat aber im Vergleich zu erhebliche GeschwindigkeitsgewinneSerializable
.Teilen Sie Daten, ohne auf der Festplatte zu bleiben
Es ist möglich, Daten zwischen Aktivitäten auszutauschen, indem sie im Speicher gespeichert werden, da in den meisten Fällen beide Aktivitäten im selben Prozess ausgeführt werden.
Hinweis: Manchmal, wenn der Benutzer Ihre Aktivität verlässt (ohne sie zu beenden), entscheidet sich Android möglicherweise dafür, Ihre Anwendung zu beenden. In einem solchen Szenario habe ich Fälle erlebt, in denen Android versucht, die letzte Aktivität mit der vor dem Beenden der App angegebenen Absicht zu starten. In diesem Fall gehen die in einem Singleton gespeicherten Daten (entweder Ihre oder Ihre
Application
) verloren und es können schlimme Dinge passieren. Um solche Fälle zu vermeiden, behalten Sie entweder Objekte auf der Festplatte bei oder überprüfen Daten, bevor Sie sie verwenden, um sicherzustellen, dass sie gültig sind.Verwenden Sie eine Singleton-Klasse
Haben Sie eine Klasse, um die Daten zu halten:
Aus der gestarteten Aktivität:
Verwenden Sie die Anwendung Singleton
Der Anwendungs-Singleton ist eine Instanz,
android.app.Application
die beim Start der App erstellt wird. Sie können eine benutzerdefinierte bereitstellen, indem Sie Folgendes erweiternApplication
:Vor dem Starten der Aktivität:
Dann aus der gestarteten Aktivität:
Statische Felder
Die Idee ist im Grunde die gleiche wie beim Singleton, aber in diesem Fall bieten Sie statischen Zugriff auf die Daten:
Aus der gestarteten Aktivität:
HashMap von
WeakReferences
Dieselbe Idee, aber dem Garbage Collector erlauben, nicht referenzierte Objekte zu entfernen (z. B. wenn der Benutzer die Aktivität beendet):
Vor dem Starten der Aktivität:
Aus der gestarteten Aktivität:
Möglicherweise müssen Sie die Objekt-ID mithilfe der Extras der Absicht übergeben oder nicht. Es hängt alles von Ihrem spezifischen Problem ab.
Objekte auf der Festplatte beibehalten
Die Idee ist, die Daten auf der Festplatte zu speichern, bevor die andere Aktivität gestartet wird.
Vorteile: Sie können die Aktivität von anderen Orten aus starten. Wenn die Daten bereits gespeichert sind, sollten sie einwandfrei funktionieren.
Nachteile: Die Implementierung ist umständlich und dauert länger. Benötigt mehr Code und damit mehr Chancen, Fehler einzuführen. Es wird auch viel langsamer sein.
Einige der Möglichkeiten, Objekte beizubehalten, umfassen:
quelle
setResult
Methode. In diesem Fall muss die sekundäre Aktivität auch mithilfe derstartActivityForResult
Methode aufgerufen werden .Activity
durchgehend undonCreate()
überprüfen Sie bei der Überprüfung jedes statische Feld des Singletons, das Sie beim Starten der App ausfüllen. Wenn dieses Feld leer ist, kehren Sie mitFLAG_ACTIVITY_CLEAR_TASK
oder aBroadcastReceiver
zur Startaktivität zurück, um andere Aktivitäten zu beenden.Was Sie verwenden können:
Was Sie wählen, hängt von Ihren Bedürfnissen ab. Wahrscheinlich werden Sie mehr als einen Weg benutzen, wenn Sie "viel" haben.
quelle
MAIN
Aktion aus neu gestartet . Nach dem Prozessstart starten Sie die zuletzt geöffnete Aktivität neu. Dies kann eine Detailseite irgendwo tief in der App sein.Tun Sie, was Google Ihnen befiehlt! hier: http://developer.android.com/resources/faq/framework.html#3
quelle
Das macht keine Kopie (besonders mit String , aber selbst Objekte werden als Wert der Referenz übergeben, nicht des Objekts selbst, und solche Getter sind in Ordnung zu verwenden - wohl besser zu verwenden als andere Mittel, weil sie gemeinsam sind und gut verstanden). Die älteren "Leistungsmythen", wie das Verzichten auf Getter und Setter, haben immer noch einen gewissen Wert, wurden aber auch in den Dokumenten aktualisiert .
Wenn Sie dies jedoch nicht möchten, können Sie die Variablen auch einfach in GlobalState öffentlich oder geschützt machen und direkt darauf zugreifen. Und Sie können einen statischen Singleton erstellen, wie das Anwendungsobjekt JavaDoc angibt :
Die Verwendung von Absichtsdaten , wie andere Antworten hier vermerken, ist eine andere Möglichkeit, Daten zu übergeben, wird jedoch normalerweise für kleinere Daten und einfache Typen verwendet. Sie können größere / komplexere Daten übergeben, dies ist jedoch aufwändiger als die Verwendung eines statischen Singleons. Das Anwendungsobjekt ist immer noch mein persönlicher Favorit für die gemeinsame Nutzung größerer / komplexerer nicht persistenter Daten zwischen Android-Anwendungskomponenten (da es in einer Android-App einen genau definierten Lebenszyklus aufweist).
Wie andere bereits bemerkt haben, können Sie auch SQLite oder das Dateisystem verwenden , wenn die Daten sehr komplex werden und persistent sein müssen .
quelle
Sie können die Anwendungsklasse und das Tag für alle gewünschten Objekte erweitern. Diese sind dann an einer beliebigen Stelle in Ihrer Anwendung verfügbar
quelle
Es gibt eine neue und bessere Möglichkeit, Daten zwischen Aktivitäten auszutauschen , und es handelt sich um LiveData . Beachten Sie insbesondere dieses Zitat von der Android-Entwicklerseite:
Dies hat enorme Auswirkungen: Alle Modelldaten können in einer gemeinsamen Singleton-Klasse in einem
LiveData
Wrapper gemeinsam genutzt werden. Es kann ausViewModel
Gründen der Testbarkeit aus den Aktivitäten in ihre jeweiligen injiziert werden . Und Sie müssen sich keine Sorgen mehr über schwache Referenzen machen, um Speicherverluste zu vermeiden.quelle
Die Verwendung der oben beschriebenen Hashmap des schwachen Referenzansatzes und unter http://developer.android.com/guide/faq/framework.html erscheint mir problematisch. Wie werden ganze Einträge zurückgefordert, nicht nur der Kartenwert? In welchem Umfang ordnen Sie es zu? Da das Framework die Kontrolle über den Aktivitätslebenszyklus hat und eine der teilnehmenden Aktivitäten besitzt, besteht die Gefahr von Laufzeitfehlern, wenn der Eigentümer vor seinen Kunden zerstört wird. Wenn die Anwendung Eigentümerin ist, muss eine Aktivität den Eintrag explizit entfernen, um zu verhindern, dass die Hashmap Einträge mit einem gültigen Schlüssel und einer möglicherweise in der Müllhalde gesammelten schwachen Referenz festhält. Was sollte ein Client außerdem tun, wenn der für einen Schlüssel zurückgegebene Wert null ist?
Es scheint mir, dass eine WeakHashMap, die der Anwendung oder einem Singleton gehört, die bessere Wahl ist. Auf einen Wert in der Karte wird über ein Schlüsselobjekt zugegriffen. Wenn keine starken Verweise auf den Schlüssel vorhanden sind (dh alle Aktivitäten werden mit dem Schlüssel und dessen Zuordnung ausgeführt), kann GC den Karteneintrag zurückfordern.
quelle
Es gibt verschiedene Möglichkeiten, Daten zwischen Aktivitäten auszutauschen
1: Übergeben von Daten zwischen Aktivitäten mit Intent
2: Definieren Sie die Variable mit dem Schlüsselwort static als public static und verwenden Sie eine beliebige Stelle im Projekt
Verwenden Sie irgendwo im Projekt mithilfe von classname.variableName.
3: Verwenden der Datenbank
Da der Prozess jedoch etwas langwierig ist, müssen Sie eine Abfrage zum Einfügen von Daten verwenden und Daten bei Bedarf mit dem Cursor iterieren. Es besteht jedoch keine Möglichkeit, Daten zu verlieren, ohne den Cache zu bereinigen.
4: Gemeinsame Einstellungen verwenden
viel einfacher als Datenbank. Es gibt jedoch einige Einschränkungen, dass Sie ArrayList-, List- und Custome-Objekte nicht speichern können.
5: Erstellen Sie einen Getter-Setter in der Aplication-Klasse und greifen Sie auf alle Stellen im Projekt zu.
hier setzen und von Aktivitäten bekommen
quelle
Nun, ich habe ein paar Ideen, aber ich weiß nicht, ob sie das sind, wonach Sie suchen.
Sie können einen Dienst verwenden, der alle Daten enthält, und dann Ihre Aktivitäten einfach an den Dienst binden, um Daten abzurufen.
Oder verpacken Sie Ihre Daten in eine serialisierbare oder paketierbare Datei, hängen Sie sie an ein Bundle an und übergeben Sie das Bundle zwischen den Aktivitäten.
Dieser ist möglicherweise überhaupt nicht das, wonach Sie suchen, aber Sie können auch versuchen, SharedPreferences oder eine Präferenz im Allgemeinen zu verwenden.
In jedem Fall lassen Sie mich wissen, was Sie entscheiden.
quelle
Angenommen, Sie rufen Aktivität zwei von Aktivität eins mit einer Absicht auf.
Sie können die Daten mit dem intent.putExtra () übergeben.
Nehmen Sie dies als Referenz. Senden von Arrays mit Intent.putExtra
Hoffe das ist was du willst.
quelle
Wenn Ihre Absicht andere Aktivitäten ist von der aktuellen Aktivität zu rufen, sollten Sie verwenden Intents . Ihr Fokus könnte weniger auf dem Bestehen von Daten als auf dem Teilen nach Bedarf liegen.
Wenn Sie diese Werte jedoch wirklich beibehalten müssen, können Sie sie in einer strukturierten Textdatei oder Datenbank im lokalen Speicher beibehalten. Eine Eigenschaftendatei, XML-Datei oder JSON-Datei kann Ihre Daten speichern und während der Aktivitätserstellung leicht analysiert werden. Vergessen Sie auch nicht, dass Sie SQLite auf allen Android-Geräten haben, damit Sie sie in einer Datenbanktabelle speichern können. Sie können auch eine Map verwenden, um Schlüssel-Wert-Paare zu speichern und die Map in den lokalen Speicher zu serialisieren. Dies ist jedoch möglicherweise zu umständlich, um für einfache Datenstrukturen nützlich zu sein.
quelle
Alle oben genannten Antworten sind großartig ... Ich füge nur eine hinzu, die noch niemand über das Fortbestehen von Daten durch Aktivitäten erwähnt hat, und das heißt, die integrierte Android SQLite-Datenbank zu verwenden, um relevante Daten beizubehalten ... Tatsächlich können Sie Ihre platzieren databaseHelper im Anwendungsstatus und rufen Sie ihn während der gesamten Aktivierung nach Bedarf auf. Oder erstellen Sie einfach eine Hilfsklasse und führen Sie die DB-Aufrufe bei Bedarf aus. Fügen Sie einfach eine weitere Ebene hinzu, die Sie berücksichtigen sollten. Alle anderen Antworten würden jedoch ausreichen auch .. Wirklich nur Präferenz
quelle
Das Teilen von Daten zwischen Aktivitäten, z. B. das Übergeben einer E-Mail nach dem Anmelden
"E-Mail" ist der Name, mit dem auf den Wert der angeforderten Aktivität verwiesen werden kann
1 Code auf der Anmeldeseite
2 Code auf der Homepage
quelle
Und wenn Sie mit Datenobjekten arbeiten möchten, sind diese beiden Implementierungen sehr wichtig:
Serializable vs Parcelable
public class User implements Parcelable
Checken Sie hier mehr ein
quelle