Qual è la differenza tra commit () e apply () in SharedPreferences


431

Sto usando SharedPreferencesnella mia app Android. Sto usando sia commit()e apply()metodo dalla preferenza condivisa. Quando uso AVD 2.3 non mostra alcun errore, ma quando eseguo il codice in AVD 2.1, il apply()metodo mostra l'errore.

Quindi qual è la differenza tra questi due? E utilizzando solo commit()posso memorizzare il valore della preferenza senza alcun problema?


115
Questo è un anno, ma ho intenzione di commentarlo comunque, anche se può essere ovvio, nessuna delle risposte fa questo punto: apply()eseguirà gli I / O su disco in modo asincrono mentre commit()è sincrono. Quindi non dovresti davvero chiamare commit()dal thread dell'interfaccia utente.
michiakig,

Da notare, quando sono in uso più oggetti SharedPreferences.Editor, l'ultimo a chiamare apply()vince. Pertanto, è possibile utilizzare apply()al posto di commit()sicuro se si assicura che un solo SharedPreferences.Editor sia utilizzato dall'applicazione.
aoeu,

2
Come da avviso di Android Studio Lint: commit () salverà i dati immediatamente e in modo sincrono. Tuttavia, apply () lo salverà in modo asincrono (in background) e quindi migliorerà alcune prestazioni. Questo è il motivo per cui apply () è preferito su commit () se non ti interessa il suo tipo di ritorno (Se i dati vengono salvati correttamente o meno).
Rahul Raina,

Esiste un modo per disabilitare l'avviso Lint durante l'utilizzo commit()?
QED

Risposte:


653

apply()è stato aggiunto in 2.3, si impegna senza restituire un valore booleano che indica successo o fallimento.

commit()restituisce vero se il salvataggio funziona, falso altrimenti.

apply() è stato aggiunto poiché il team di sviluppatori Android ha notato che quasi nessuno ha notato il valore di ritorno, quindi applicare è più veloce in quanto asincrono.

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


8
Questa risposta è vera ma immagino che anche il commento di @spacemanaki sopra sia vero contenga informazioni preziose
Aksel Fatih

58
commit () scrive immediatamente i suoi dati nella memoria permanente, mentre apply () li gestirà in background.
capt.swag

18
crea una condizione di gara?
ChrisMcJava,

42
Cosa succede se scrivo qualcosa con apply () e provo a leggerlo subito dopo? La lettura è garantita per darmi il valore più recente? I documenti dicono che se un altro commit () si verifica dopo che si esegue apply (), quel commit () si bloccherà fino a quando si applica () il disco, il che chiarisce che questo problema non si verifica quando si tratta di operazioni di "scrittura" , ma se scrivessi e leggessi subito dopo? Dai miei test, viene restituito il valore più recente, ma voglio sapere se questo è garantito al 100% o meno.
Tiago,

22
è sicuro sostituire qualsiasi istanza di commit () con apply () vedere developer.android.com/reference/android/content/…
Tigran Sarkisian,

221

tl; dr:

  • commit()scrive i dati in modo sincrono (bloccando il thread da cui viene chiamato). Ti informa quindi del successo dell'operazione.
  • apply()pianifica i dati da scrivere in modo asincrono . Non ti informa del successo dell'operazione.
  • Se si salva con apply()e si legge immediatamente tramite qualsiasi metodo getX, verrà restituito il nuovo valore!
  • Se apply()ad un certo punto hai chiamato e sta ancora eseguendo, tutte le chiamate a commit()verranno bloccate fino al termine di tutte le precedenti chiamate di applicazione e la chiamata di commit corrente.

Informazioni più dettagliate dalla documentazione di SharedPreferences.Editor :

A differenza di commit (), che scrive le sue preferenze in modo persistente sull'archiviazione persistente , apply () commette immediatamente le modifiche alle condivisioni condivise in memoria ma avvia un commit asincrono sul disco e non verrà notificato alcun errore . Se un altro editor su questo SharedPreferences esegue un commit regolare () mentre un apply () è ancora in sospeso, il commit () si bloccherà fino al completamento di tutti i commit asincroni e il commit stesso.

Poiché le istanze di SharedPreferences sono singleton all'interno di un processo, è sicuro sostituire qualsiasi istanza di commit () con apply () se si stava già ignorando il valore restituito.

L'interfaccia SharedPreferences.Editor non dovrebbe essere implementata direttamente. Tuttavia, se in precedenza lo hai implementato e ora ricevi errori sulla mancanza di apply (), puoi semplicemente chiamare commit () da apply ().


19
Questa è una risposta molto migliore poiché menziona che apply()è asincrona e le scritture in sospeso bloccano le chiamate future commit().
spaaarky21,

22

Riscontro alcuni problemi usando apply () invece commit (). Come affermato in precedenza in altre risposte, apply () è asincrono. Sto riscontrando il problema che le modifiche formate in una preferenza "string set" non vengono mai scritte nella memoria persistente.

Succede se "imponi la detenzione" del programma o, nella ROM che ho installato sul mio dispositivo con Android 4.1, quando il processo viene interrotto dal sistema per necessità di memoria.

Consiglio di usare "commit ()" invece di "apply ()" se vuoi che le tue preferenze siano vive.


Sei sicuro che il tuo problema non sia correlato a causa del threading simultaneo? Dopo aver inviato apply (), devi aspettare un po 'per leggere le cose che hai aggiunto, altrimenti il ​​thread dell'interfaccia utente tenterà di leggere prima che il thread di lavoro di apply () abbia eseguito le modifiche.
Marco Altran,

Per quanto riguarda la serie di stringa, stackoverflow.com/questions/16820252/...~~V~~singular~~3rd
Tapirboy

@JoseLSegura - i documenti suggeriscono diversamente: developer.android.com/intl/ja/reference/android/content/… "Non devi preoccuparti dei cicli di vita dei componenti Android e della loro interazione con la scrittura su disco di apply (). si assicura che le scritture su disco in volo da apply () siano complete prima di cambiare stato. " Mi chiedo se quello che stai vedendo sia un bug in Android, e in tal caso se è stato corretto nelle versioni più recenti.
ToolmakerSteve

Lo stesso problema mi stava accadendo usando la libreria "ProcessPhoenix" per ripristinare la mia app. Stavo salvando una preferenza poco prima di eseguire un ripristino e "applica" non funzionava.
ElYeante

14

Usa apply ().

Scrive immediatamente le modifiche nella RAM e attende e le scrive nella memoria interna (il file delle preferenze effettive) dopo. Commit scrive le modifiche in modo sincrono e direttamente nel file.


14
  • commit()è sincrono, apply()è asincrono

  • apply() è la funzione nulla.

  • commit() restituisce true se i nuovi valori sono stati scritti correttamente nella memoria permanente.

  • apply() garanzie complete prima di cambiare stato, non devi preoccuparti del ciclo di vita dei componenti Android

Se non usi il valore restituito da commit()e stai usando commit()dal thread principale, usa apply()invece di commit()


13

I documenti forniscono una spiegazione abbastanza buona della differenza tra apply()e commit():

Diversamente commit(), che scrive le sue preferenze in modo persistente sull'archiviazione persistente, apply()esegue SharedPreferencesimmediatamente il commit delle modifiche in memoria, ma avvia un commit asincrono sul disco e non verrà notificato alcun errore. Se un altro editor su questo SharedPreferencesfa regolarmente commit()mentre a apply()è ancora in sospeso, commit()si bloccherà fino al completamento di tutti i commit asincroni così come il commit stesso. Dato che le SharedPreferencesistanze sono singoli in un processo, è sicuro sostituire qualsiasi istanza di commit()con apply()se si stesse già ignorando il valore restituito.


6

Da javadoc:

A differenza di commit (), che scrive le sue preferenze in modo persistente sull'archiviazione persistente, apply () commette immediatamente le modifiche alle condivisioni condivise in memoria ma avvia un commit asincrono su disco e non riceverai notifiche di errori. Se un altro editor su questo SharedPreferences esegue un commit regolare () mentre un> apply () è ancora in sospeso, il commit () si bloccherà fino al completamento di tutti i commit asincroni e il commit stesso


1

La differenza tra commit () e apply ()

Potremmo essere confusi da questi due termini, quando stiamo usando SharedPreference. Fondamentalmente sono probabilmente gli stessi, quindi chiariamo le differenze di commit () e apply ().

Valore di ritorno:

apply()si impegna senza restituire un valore booleano che indica l'esito positivo o negativo. commit() restituisce true se il salvataggio funziona, false in caso contrario.

  1. Velocità:

apply()è più veloce. commit()è più lento.

  1. Asincrono vs Sincrono:

apply(): Asincrono commit(): sincrono

  1. Atomico:

apply(): atomico commit(): atomico

  1. Notifica errore:

apply(): No commit(): Sì


Come è apply()"più veloce" di commit()? Rappresentano essenzialmente uno stesso compito che verrebbe inserito nel Looper del thread. commit()mette quell'attività nel Looper principale mentre lo apply()porta in background, mantenendo così il looper principale libero dall'attività I / O del disco.
Taseer,

A differenza di commit (), che scrive le sue preferenze in modo persistente sull'archiviazione persistente, apply () commette immediatamente le modifiche alle condivisioni condivise in memoria ma avvia un commit asincrono sul disco e non verrà notificato alcun errore. Se un altro editor su questo SharedPreferences esegue un commit regolare () mentre un apply () è ancora in sospeso, il commit () si bloccherà fino al completamento di tutti i commit asincroni e il commit stesso vedrà lo sviluppatore
Chanaka Weerasinghe il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.