Usar valores salvos   Parte do Android Jetpack.

Este tópico descreve como armazenar e usar valores de Preference que são salvos pela biblioteca Preference.

Armazenamento de dados de preferências

Esta seção descreve como uma Preference pode manter dados.

SharedPreferences

Por padrão, uma Preference usa SharedPreferences para salvar valores. A API SharedPreferences permite a leitura e a gravação de pares de chave-valor simples a partir de um arquivo que é salvo nas sessões do aplicativo. A Biblioteca Preference usa uma instância privada de SharedPreferences para que somente seu aplicativo possa acessá-la.

Como exemplo, considere o seguinte SwitchPreferenceCompat:

<SwitchPreferenceCompat
        app:key="notifications"
        app:title="Enable message notifications"/>

Quando um usuário muda esse interruptor para o estado On, o arquivo SharedPreferences é atualizado com um par de chave-valor de "notifications" : "true". A chave usada é a mesma que a definida para a Preference.

Para saber mais sobre a API SharedPreferences, consulte Salvar dados chave-valor.

Para ver informações sobre as diferentes maneiras de armazenar dados no Android, consulte Visão geral do armazenamento de dados e arquivos.

PreferenceDataStore

Embora a biblioteca Preference mantenha os dados com SharedPreferences por padrão, SharedPreferences nem sempre é a solução ideal. Por exemplo, se o app exige que um usuário faça login, convém manter as configurações do aplicativo na nuvem para que elas sejam refletidas em outros dispositivos e plataformas. Da mesma forma, se o app tiver opções de configuração específicas do dispositivo, cada usuário no dispositivo terá configurações separadas, fazendo com que SharedPreferences não seja uma solução ideal.

Um PreferenceDataStore permite que você use um back-end de armazenamento personalizado para manter valores de Preference. Para saber mais, consulte Como usar um armazenamento de dados personalizado.

Como ler valores de preferência

Para recuperar o objeto SharedPreferences que está sendo usado, chame PreferenceManager.getDefaultSharedPreferences(). Esse método funciona em qualquer lugar do seu app. Por exemplo, considerando EditTextPreference com uma chave de "assinatura":

<EditTextPreference
        app:key="signature"
        app:title="Your signature"/>

O valor salvo para essa Preference pode ser recuperado globalmente da seguinte maneira:

Kotlin

val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this /* Activity context */)
val name = sharedPreferences.getString("signature", "")

Java

SharedPreferences sharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
String name = sharedPreferences.getString(“signature”, "");

Detectar as mudanças nos valores de preferência

Para detectar mudanças em valores de Preference, você pode escolher entre duas interfaces:

A tabela abaixo mostra as diferenças entre essas duas interfaces:

OnPreferenceChangeListener OnSharedPreferenceChangeListener
Definida com base em preferências Aplicada a todas as preferências
Chamada quando uma preferência está prestes a mudar o valor salvo. Inclui se o valor pendente é o mesmo que o valor salvo no momento. Chamada somente quando o valor salvo para uma preferência muda.
Chamada somente pela biblioteca Preference. Uma parte separada do aplicativo pode mudar o valor salvo. Chamada sempre que o valor salvo muda, mesmo que seja de uma parte separada do app.
Chamada antes de o valor pendente ser salvo. Chamada depois que o valor já foi salvo.
Chamada ao usar SharedPreferences ou PreferenceDataStore. Chamada somente ao usar SharedPreferences.

OnPreferenceChangeListener

A implementação de um OnPreferenceChangeListener permite detectar quando o valor de uma Preference está prestes a mudar. A partir daí, você pode validar se essa mudança precisa mesmo ocorrer. Por exemplo, o código abaixo mostra como detectar uma mudança no valor de uma EditTextPreference com uma chave de "nome":

Kotlin

override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
    Log.e("preference", "Pending Preference value is: $newValue")
    return true
}

Java

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    Log.e("preference", "Pending Preference value is: " + newValue);
    return true;
}

Em seguida, você precisa definir esse listener diretamente com setOnPreferenceChangeListener(), conforme mostrado a seguir.

Kotlin

preference.onPreferenceChangeListener = ...

Java

preference.setOnPreferenceChangeListener(...);

OnSharedPreferenceChangeListener

Ao manter valores de Preference usando SharedPreferences, você também pode usar um SharedPreferences.OnSharedPreferenceChangeListener para detectar mudanças. Isso permite que você detecte quando os valores salvos pela sua Preference mudam, por exemplo, ao sincronizar as configurações com um servidor. O exemplo abaixo mostra como detectar quando o valor de uma EditTextPreference com uma chave de "nome" muda.

Kotlin

override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
    if (key == "signature") {
        Log.i(TAG, "Preference value was updated to: " + sharedPreferences.getString(key, ""))
    }
}

Java

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (key.equals(“signature”)) {
        Log.i(TAG, “Preference value was updated to: “ + sharedPreferences.getString(key, ""));
    }
}

Você também precisa registrar o listener via registerOnSharedPreferenceChangedListener(), conforme mostrado a seguir.

Kotlin

preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(...)

Java

getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(...);

Kotlin

val listener: SharedPreferences.OnSharedPreferenceChangeListener =
        SharedPreferences.OnSharedPreferenceChangeListener {...}

Java

SharedPreferences.OnSharedPreferenceChangeListener listener =
        new SharedPreferences.OnSharedPreferenceChangeListener() {...}

Para um gerenciamento adequado do ciclo de vida em Activity ou Fragment, registre e cancele o registro desse listener nos callbacks onResume() e onPause(), conforme mostrado a seguir.

Kotlin

override fun onResume() {
    super.onResume()
    preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
}

override fun onPause() {
    super.onPause()
    preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
}

Java

@Override
public void onResume() {
    super.onResume();
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause() {
    super.onPause();
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}

Como usar um armazenamento de dados personalizado

Embora a persistência de objetos de Preference usando SharedPreferences seja recomendada, também é possível usar um armazenamento de dados personalizado. Um armazenamento de dados personalizado pode ser útil quando o aplicativo mantém valores em um banco de dados ou se os valores são específicos do dispositivo, por exemplo.

Implementar o armazenamento de dados

Para implementar um armazenamento de dados personalizado, primeiro crie uma classe que estenda PreferenceDataStore. O exemplo abaixo cria um armazenamento de dados que gerencia valores String:

Kotlin

class DataStore : PreferenceDataStore() {
    override fun putString(key: String, value: String?) {
        // Save the value somewhere
    }

    override fun getString(key: String, defValue: String?): String? {
        // Retrieve the value
    }
}

Java

public class DataStore extends PreferenceDataStore {
    @Override
    public void putString(String key, @Nullable String value) {
        // Save the value somewhere
    }
    @Override
    @Nullable
    public String getString(String key, @Nullable String defValue) {
        // Retrieve the value
    }
}

Execute operações demoradas fora linha de execução principal para evitar o bloqueio da interface do usuário. Como é possível que o armazenamento de dados Fragment ou Activity seja destruído ao manter um valor, você precisa serializar os dados para não perder nenhum valor alterado pelo usuário.

Ativar o armazenamento de dados

Depois de implementar seu armazenamento de dados, você precisa definir o novo armazenamento de dados em onCreatePreferences() para que objetos Preference mantenham valores com o armazenamento de dados em vez de usar SharedPreferences. Um armazenamento de dados pode ser ativado para cada Preference ou para toda a hierarquia.

Para ativar um armazenamento de dados personalizado para uma Preference específica, chame setPreferenceDataStore() em Preference, conforme mostrado no exemplo abaixo:

Kotlin

val preference: Preference? = findPreference("key")
preference?.preferenceDataStore = dataStore

Java

Preference preference = findPreference(“key”);
if (preference != null) {
    preference.setPreferenceDataStore(dataStore);
}

Para ativar um armazenamento de dados personalizado para toda a hierarquia, chame setPreferenceDataStore() no PreferenceManager:

Kotlin

val preferenceManager = preferenceManager
preferenceManager.preferenceDataStore = dataStore

Java

PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setPreferenceDataStore(dataStore);

Um armazenamento de dados definido para um Preference específico substitui qualquer armazenamento de dados que esteja definido para a hierarquia correspondente. Na maioria dos casos, você precisa definir um armazenamento de dados para toda a hierarquia.