Was ist der Unterschied zwischen commit () und apply () in SharedPreferences?

432

Ich benutze SharedPreferencesin meiner Android App. Ich benutze beide commit()und apply()Methode aus gemeinsamen Präferenzen. Wenn ich AVD 2.3 verwende, wird kein Fehler angezeigt. Wenn ich jedoch den Code in AVD 2.1 ausführe, apply()zeigt die Methode einen Fehler an.

Was ist der Unterschied zwischen diesen beiden? Und wenn commit()ich nur benutze, kann ich den Präferenzwert problemlos speichern?

Andro Selva
quelle
115
Dies ist ein Jahr alt, aber ich werde es trotzdem kommentieren, obwohl es offensichtlich sein mag, macht keine der Antworten diesen Punkt: apply()Wird asynchron Festplatten-E / A ausführen, während commit()es synchron ist. Sie sollten also wirklich nicht commit()vom UI-Thread aus aufrufen .
michiakig
Wenn mehrere SharedPreferences.Editor-Objekte verwendet werden, apply()gewinnt das letzte, das aufgerufen wird . Daher können Sie apply()anstelle von commit()sicher verwenden, wenn Sie sicherstellen, dass nur eine SharedPreferences.Editor von Ihrer Anwendung verwendet wird.
Aoeu
2
Gemäß der Warnung von Android Studio Lint: commit () speichert Daten sofort und synchron. Apply () speichert es jedoch asynchron (im Hintergrund) und verbessert dadurch die Leistung. Aus diesem Grund wird apply () gegenüber commit () bevorzugt, wenn Sie sich nicht für den Rückgabetyp interessieren (ob die Daten erfolgreich gespeichert wurden oder nicht).
Rahul Raina
Gibt es eine Möglichkeit, die Flusenwarnung bei Verwendung zu deaktivieren commit()?
QED

Antworten:

654

apply()wurde in 2.3 hinzugefügt, es wird festgeschrieben, ohne einen Booleschen Wert zurückzugeben, der Erfolg oder Misserfolg anzeigt.

commit()Gibt true zurück , wenn das Speichern funktioniert, andernfalls false .

apply() wurde hinzugefügt, als das Android-Entwicklerteam bemerkte, dass fast niemand den Rückgabewert zur Kenntnis nahm. Daher ist die Anwendung schneller als asynchron.

http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply ()

Ray Britton
quelle
8
Diese Antwort ist wahr, aber ich denke, der obige Kommentar von @spacemanaki ist auch wahr und enthält wertvolle Informationen
Aksel Fatih
58
commit () schreibt seine Daten sofort in den persistenten Speicher, während apply () sie im Hintergrund verarbeitet.
capt.swag
18
schafft es eine Rennbedingung?
ChrisMcJava
42
Was passiert, wenn ich etwas mit apply () schreibe und versuche, es sofort danach zu lesen? Gibt mir das Lesen garantiert den neuesten Wert? Die Dokumente sagen, wenn ein anderes commit () nach dem Auslösen von apply () auftritt, wird dieses commit () blockiert, bis das apply () auf der Festplatte erhalten bleibt. Dies macht deutlich, dass dieses Problem beim Schreiben nicht auftritt , aber was ist, wenn Sie gleich danach schreiben und lesen? Aus meinen Tests wird der neueste Wert zurückgegeben, aber ich möchte wissen, ob dies zu 100% garantiert ist oder nicht.
Tiago
22
Es ist sicher, jede Instanz von commit () durch apply () zu ersetzen, siehe developer.android.com/reference/android/content/…
Tigran Sarkisian
221

tl; dr:

  • commit()schreibt die Daten synchron (blockiert den Thread, von dem aus er aufgerufen wird). Anschließend werden Sie über den Erfolg der Operation informiert .
  • apply()Plant die asynchron zu schreibenden Daten . Es informiert Sie nicht über den Erfolg der Operation.
  • Wenn Sie mit einer getX-Methode speichern apply()und sofort lesen , wird der neue Wert zurückgegeben!
  • Wenn Sie apply()irgendwann angerufen haben und es noch ausgeführt wird, werden alle Aufrufe von commit()blockiert, bis alle vergangenen Apply-Aufrufe und der aktuelle Commit-Aufruf beendet sind.

Weitere Informationen finden Sie in der SharedPreferences.Editor- Dokumentation:

Im Gegensatz zu () begehen, der schreibt seine Vorlieben aus dem Dauerspeicher synchron , apply () verpflichtet sich, seine Änderungen an den im Speicher SharedPreferences sofort , sondern beginnt ein asynchroner auf die Festplatte zu begehen , und Sie werden nicht von irgendwelchen Fehlern benachrichtigt . Wenn ein anderer Editor in diesen SharedPreferences ein reguläres Commit () ausführt, während ein apply () noch aussteht, wird das commit () blockiert, bis alle asynchronen Commits sowie das Commit selbst abgeschlossen sind.

Da SharedPreferences-Instanzen Singletons innerhalb eines Prozesses sind, können Sie jede Instanz von commit () durch apply () ersetzen, wenn Sie den Rückgabewert bereits ignoriert haben.

Es wird nicht erwartet, dass die SharedPreferences.Editor-Schnittstelle direkt implementiert wird. Wenn Sie es jedoch zuvor implementiert haben und jetzt Fehler bezüglich fehlender apply () erhalten, können Sie einfach commit () von apply () aus aufrufen.

Lukas Knuth
quelle
19
Dies ist eine viel bessere Antwort, da erwähnt wird, dass apply()asynchrone und ausstehende Schreibvorgänge zukünftige Aufrufe blockieren commit().
spaaarky21
22

Ich habe einige Probleme mit apply () anstelle von commit (). Wie bereits in anderen Antworten erwähnt, ist apply () asynchron. Ich habe das Problem, dass die Änderungen, die an einer "Zeichenfolgensatz" -Einstellung vorgenommen wurden, niemals in den persistenten Speicher geschrieben werden.

Es passiert, wenn Sie das Programm "erzwingen" oder in dem ROM, das ich mit Android 4.1 auf meinem Gerät installiert habe, wenn der Prozess vom System aufgrund von Speicherbedarf abgebrochen wird.

Ich empfehle, "commit ()" anstelle von "apply ()" zu verwenden, wenn Sie möchten, dass Ihre Einstellungen lebendig bleiben.

JoseLSegura
quelle
Sind Sie sicher, dass Ihr Problem nicht mit gleichzeitigem Threading zusammenhängt? Nachdem Sie apply () gesendet haben, müssen Sie eine Weile warten, um die hinzugefügten Elemente zu lesen. Andernfalls versucht der UI-Thread zu lesen, bevor der Worker-Thread von apply () die Änderungen festgeschrieben hat.
Marco Altran
In Bezug auf den String-Satz, stackoverflow.com/questions/16820252/…
Tapirboy
@JoseLSegura - Die Dokumente schlagen etwas anderes vor: developer.android.com/intl/ja/reference/android/content/… "Sie müssen sich keine Gedanken über den Lebenszyklus von Android-Komponenten und deren Interaktion mit dem Schreiben von apply () auf die Festplatte machen. Das Framework stellt sicher, dass die Schreibvorgänge während des Flugs von apply () abgeschlossen sind, bevor der Status gewechselt wird. " Ich frage mich, ob das, was Sie sehen, ein Fehler in Android ist und wenn ja, ob er in neueren Versionen behoben wurde.
ToolmakerSteve
Das gleiche Problem trat bei der Verwendung der Bibliothek "ProcessPhoenix" zum Zurücksetzen meiner App auf. Ich habe kurz vor dem Zurücksetzen eine Voreinstellung gespeichert und "Anwenden" hat nicht funktioniert.
ElYeante
14

Verwenden Sie apply ().

Es schreibt die Änderungen sofort in den RAM und wartet und schreibt sie anschließend in den internen Speicher (die eigentliche Voreinstellungsdatei). Commit schreibt die Änderungen synchron und direkt in die Datei.

Mustafa
quelle
14
  • commit()ist synchron, apply()ist asynchron

  • apply() ist nichtige Funktion.

  • commit() Gibt true zurück, wenn die neuen Werte erfolgreich in den dauerhaften Speicher geschrieben wurden.

  • apply() Garantien vollständig, bevor Sie den Status wechseln. Sie müssen sich keine Gedanken über den Lebenszyklus von Android-Komponenten machen

Wenn Sie den von commit()und commit()vom Hauptthread zurückgegebenen Wert nicht verwenden , verwenden Sie apply()anstelle von commit()

Nurlan Sofiyev
quelle
13

Die Dokumente geben eine ziemlich gute Erklärung für den Unterschied zwischen apply()und commit():

Im Gegensatz dazu commit(), bei dem die Einstellungen synchron in den persistenten Speicher geschrieben werden, werden apply()die Änderungen SharedPreferencessofort im Arbeitsspeicher festgeschrieben, es wird jedoch eine asynchrone Festschreibung auf die Festplatte gestartet, und Sie werden nicht über Fehler benachrichtigt. Wenn ein anderer Editor dies SharedPreferencesregelmäßig tut, commit()während a apply()noch aussteht, commit()wird der Block blockiert, bis alle asynchronen Commits sowie das Commit selbst abgeschlossen sind. Als SharedPreferencesBeispiele Singletons innerhalb eines Prozesses sind, ist es sicher jede Instanz ersetzen commit()mit , apply()wenn Sie bereits wurden den Rückgabewert ignoriert.

Mojo Risin
quelle
6

Aus Javadoc:

Im Gegensatz zu commit (), das seine Einstellungen synchron in den persistenten Speicher schreibt, schreibt apply () seine Änderungen sofort in die speicherinternen SharedPreferences, startet jedoch ein asynchrones Commit auf die Festplatte und Sie werden nicht über Fehler benachrichtigt. Wenn ein anderer Editor in diesen SharedPreferences ein reguläres Commit () ausführt, während ein> apply () noch aussteht, wird das commit () blockiert, bis alle asynchronen Commits sowie das Commit selbst abgeschlossen sind

Vladimir Ivanov
quelle
1

Der Unterschied zwischen commit () und apply ()

Diese beiden Begriffe könnten uns verwirren, wenn wir SharedPreference verwenden. Grundsätzlich sind sie wahrscheinlich gleich. Lassen Sie uns also die Unterschiede zwischen commit () und apply () klären.

1. Rückgabewert:

apply()Commits ohne Rückgabe eines Booleschen Werts, der Erfolg oder Misserfolg anzeigt. commit() gibt true zurück, wenn das Speichern funktioniert, andernfalls false.

  1. Geschwindigkeit:

apply()ist schneller. commit()ist langsamer.

  1. Asynchron vs Synchron:

apply(): Asynchron commit(): Synchron

  1. Atomic:

apply(): atomar commit(): atomar

  1. Fehlerbenachrichtigung:

apply(): Nein commit(): Ja

Chanaka Weerasinghe
quelle
Wie ist apply()"schneller" als commit()? Sie stellen im Wesentlichen dieselbe Aufgabe dar, die in Looper des Threads ausgeführt wird. commit()Setzt diese Aufgabe in den Haupt-Looper, während apply()sie im Hintergrund angezeigt wird, wodurch der Haupt-Looper frei von Festplatten-E / A-Aufgaben bleibt.
Taseer
Im Gegensatz zu commit (), das seine Einstellungen synchron in den persistenten Speicher schreibt, schreibt apply () seine Änderungen sofort in die speicherinternen SharedPreferences, startet jedoch ein asynchrones Commit auf die Festplatte und Sie werden nicht über Fehler benachrichtigt. Wenn ein anderer Editor in diesen SharedPreferences ein reguläres Commit () ausführt, während ein apply () noch aussteht, wird das commit () blockiert, bis alle asynchronen Commits abgeschlossen sind, sowie das Commit selbst (siehe DOC developer.android.com/reference/). android / content /…
Chanaka Weerasinghe