Qual é a diferença entre commit () e apply () em SharedPreferences

431

Estou usando SharedPreferencesno meu aplicativo Android. Estou usando ambos commit()e apply()método de preferência compartilhada. Quando uso o AVD 2.3, ele não mostra erro, mas quando executo o código no AVD 2.1, o apply()método mostra erro.

Então, qual é a diferença entre esses dois? E usando apenas commit()posso armazenar o valor da preferência sem nenhum problema?

Andro Selva
fonte
115
Este é um ano de idade, mas vou comentar sobre o assunto de qualquer maneira, embora possa ser óbvio, nenhuma das respostas faz esse ponto: apply()fará de forma assíncrona a E / S de disco enquanto commit()estiver síncrona. Portanto, você realmente não deve ligar commit()do thread da interface do usuário.
Michiakig
É importante notar que, quando vários objetos SharedPreferences.Editor estão em uso, o último a chamar apply()ganha. Portanto, você pode usar apply()em vez de commit()segurança, se garantir que apenas um SharedPreferences.Editor esteja sendo usado pelo seu aplicativo.
aoeu 28/04
2
Conforme aviso do Android Studio Lint: commit () salvará os dados imediatamente e de forma síncrona. No entanto, o apply () o salvará de forma assíncrona (em segundo plano) e, assim, melhorará o desempenho. É por isso que apply () é preferido em vez de commit () se você não se importa com seu tipo de retorno (se os dados são salvos com sucesso ou não).
Rahul Raina
Existe uma maneira de desativar o aviso de cotão ao usar commit()?
QED

Respostas:

653

apply()foi adicionado na versão 2.3, ele confirma sem retornar um valor booleano indicando sucesso ou falha.

commit()retorna verdadeiro se o salvamento funcionar, falso caso contrário.

apply() foi adicionado quando a equipe de desenvolvedores do Android percebeu que quase ninguém notava o valor de retorno, portanto, aplicar é mais rápido e assíncrono.

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

Ray Britton
fonte
8
Esta resposta é verdade, mas eu acho comentário @spacemanaki 's acima também é verdade contém informações valiosas
Aksel Fatih
58
O commit () grava seus dados no armazenamento persistente imediatamente, enquanto o apply () o manipula em segundo plano.
capt.swag
18
isso cria uma condição de corrida?
ChrisMcJava
42
O que acontece se eu escrever algo com apply () e tentar lê-lo imediatamente depois? A leitura é garantida para fornecer o valor mais recente? Os documentos dizem que se outro commit () acontecer após o acionamento de apply (), esse commit () será bloqueado até que o apply () seja persistido no disco, o que deixa claro que esse problema não ocorre quando se trata de operações de 'gravação' , mas e se você estiver escrevendo e lendo imediatamente depois? Dos meus testes, o valor mais recente é retornado, mas quero saber se isso é 100% garantido ou não.
Tiago
22
é seguro para substituir qualquer instância de commit () com apply () ver developer.android.com/reference/android/content/...
Tigran Sarkisian
221

tl; dr:

  • commit()grava os dados de forma síncrona (bloqueando o thread do qual é chamado) Em seguida, ele informa sobre o sucesso da operação.
  • apply()agenda os dados para serem gravados de forma assíncrona . Ele não informa sobre o sucesso da operação.
  • Se você salvar com apply()e ler imediatamente através de qualquer método getX, o novo valor será retornado!
  • Se você telefonou apply()em algum momento e ele ainda estiver em execução, todas as chamadas para commit()serão bloqueadas até que todas as chamadas de aplicação anteriores e a chamada de confirmação atual sejam concluídas.

Informações mais detalhadas da documentação SharedPreferences.Editor :

Diferentemente do commit (), que grava suas preferências no armazenamento persistente de forma síncrona , o apply () confirma imediatamente suas alterações nas SharedPreferences na memória, mas inicia um commit assíncrono no disco e você não será notificado sobre falhas . Se outro editor neste SharedPreferences fizer uma confirmação regular () enquanto uma aplicação () ainda estiver pendente, a confirmação () será bloqueada até que todas as confirmações assíncronas sejam concluídas, assim como a própria confirmação.

Como as instâncias SharedPreferences são singletons em um processo, é seguro substituir qualquer instância de commit () por apply () se você já estava ignorando o valor de retorno.

Não se espera que a interface SharedPreferences.Editor seja implementada diretamente. No entanto, se você o implementou anteriormente e agora está recebendo erros sobre a falta de apply (), basta chamar commit () em apply ().

Lukas Knuth
fonte
19
Essa é uma resposta muito melhor, pois menciona que apply()é assíncrono e as gravações pendentes bloqueiam futuras chamadas para commit().
spaaarky21
22

Estou com alguns problemas ao usar apply () em vez de commit (). Conforme declarado anteriormente em outras respostas, o apply () é assíncrono. Estou com o problema de que as alterações formadas em uma preferência de "conjunto de cadeias" nunca são gravadas na memória persistente.

Isso acontece se você "forçar a detenção" do programa ou, na ROM que eu instalei no meu dispositivo com Android 4.1, quando o processo é encerrado pelo sistema devido a necessidades de memória.

Eu recomendo usar "commit ()" em vez de "apply ()" se você deseja que suas preferências estejam ativas.

JoseLSegura
fonte
Tem certeza de que seu problema não está relacionado devido a segmentação simultânea? Depois de enviar o apply (), é necessário aguardar um pouco para ler o que você adicionou, caso contrário, o thread da interface do usuário tentará ler antes que o thread de trabalho do apply () confirme as alterações.
Marco Altran
Em relação conjunto de cordas, stackoverflow.com/questions/16820252/...
Tapirboy
@ JosephLSegura - os documentos sugerem o contrário: developer.android.com/intl/ja/reference/android/content/… "Você não precisa se preocupar com os ciclos de vida dos componentes do Android e sua interação com a gravação de apply () no disco. A estrutura certifica-se de que as gravações em disco em andamento de apply () sejam concluídas antes de alternar os estados. " Gostaria de saber se o que você está vendo é um bug no Android e, se sim, se foi corrigido nas versões mais recentes.
Página Inicial>
O mesmo problema aconteceu comigo usando a biblioteca "ProcessPhoenix" para redefinir meu aplicativo. Eu estava salvando uma preferência pouco antes de executar uma redefinição e "aplicar" não estava funcionando.
ElYeante 5/05
14

Use apply ().

Ele grava as alterações na RAM imediatamente e aguarda e as grava no armazenamento interno (o arquivo de preferências real) depois. A confirmação grava as alterações de forma síncrona e direta no arquivo.

Mustafa
fonte
14
  • commit()é síncrona, apply()é assíncrona

  • apply() é a função nula.

  • commit() retorna true se os novos valores foram gravados com êxito no armazenamento persistente.

  • apply() garantias completas antes de mudar de estado, você não precisa se preocupar com os ciclos de vida dos componentes do Android

Se você não usar o valor retornado commit()e estiver usando o commit()thread principal, use em apply()vez de commit()

Nurlan Sofiyev
fonte
13

Os documentos dão uma boa explicação da diferença entre apply()e commit():

Ao contrário commit(), que grava suas preferências para armazenamento persistente de forma síncrona, apply()confirma suas alterações na memória SharedPreferencesimediatamente, mas inicia uma confirmação assíncrona no disco e você não será notificado de nenhuma falha. Se outro editor SharedPreferencesfizer isso regularmente commit()enquanto a apply()ainda estiver pendente, o commit()bloco será bloqueado até que todas as confirmações assíncronas sejam concluídas, assim como a própria confirmação. Como SharedPreferencesinstâncias são singletons em um processo, é seguro substituir qualquer instância commit()por apply()se você já estiver ignorando o valor de retorno.

Mojo Risin
fonte
6

Partida javadoc:

Diferentemente do commit (), que grava suas preferências no armazenamento persistente de forma síncrona, o apply () confirma imediatamente suas alterações nas SharedPreferences na memória, mas inicia um commit assíncrono no disco e você não será notificado sobre falhas. Se outro editor neste SharedPreferences fizer um commit regular () enquanto um> apply () ainda estiver pendente, o commit () bloqueará até que todos os commit assíncronos sejam concluídos, assim como o próprio commit

Vladimir Ivanov
fonte
1

A diferença entre commit () e apply ()

Podemos ficar confusos com esses dois termos, quando estamos usando SharedPreference. Basicamente, eles provavelmente são os mesmos, então vamos esclarecer as diferenças de commit () e apply ().

1. valor de retorno:

apply()confirma sem retornar um booleano indicando sucesso ou falha. commit() retorna verdadeiro se o salvamento funcionar, caso contrário, falso.

  1. Rapidez:

apply()é mais rápido. commit()é mais lento.

  1. Assíncrono x Síncrono:

apply(): Assíncrono commit(): Síncrono

  1. Atômica:

apply(): atômico commit(): atômico

  1. Notificação de erro:

apply(): Não commit(): Sim

Chanaka Weerasinghe
fonte
Como é apply()"mais rápido" do que commit()? Representam essencialmente uma mesma tarefa que seria colocada no Looper do thread. commit()coloca essa tarefa no Looper principal e a apply()coloca em segundo plano, mantendo o looper principal livre da tarefa de E / S do disco.
Taseer
Diferentemente do commit (), que grava suas preferências no armazenamento persistente de forma síncrona, o apply () confirma imediatamente suas alterações nas SharedPreferences na memória, mas inicia um commit assíncrono no disco e você não será notificado sobre falhas. Se outro editor deste SharedPreferences fizer um commit regular () enquanto um apply () ainda estiver pendente, o commit () será bloqueado até que todas as confirmações assíncronas sejam concluídas e o próprio commit veja o DOC developer.android.com/reference/ android / content /…
Chanaka Weerasinghe 26/09/19