quinta-feira, 21 de junho de 2018

Rumo ao Certificado Android: Dados Persistentes - Shared Preferences

Hoje vou começar uma sub-série sobre persistência de dados no Android. Persistência de dados é a capacidade do aplicativo manter os dados mesmo depois do aplicativo ser finalizado. O Android possui 5 formas de lidar com persistência de dados, cada uma atendendo a uma necessidade específica.

A primeira já vimos, que é o Instance State, usado para persistir o estado de uma Activity quando o mesmo está preste a ser destruído pelo sistema sem que o usuário deseje isso. Como o usuário pode querer retomar a Activity, o ideal é que a mesma mantenha da mesma forma que o usuário deixou. Se o usuário fechar o aplicativo, então os dados do Instance State são apagados.

O segundo é o SharedPreferences, onde utiliza um arquivo e num sistema de chave/valor, permite armazenar strings. Os dados armazenados pela SharedPreferences são guardados até a desinstalação do aplicativo.

Para dados mais complexos e estruturados, o Android possui suporte nativo ao banco de dados SQLite, podendo criar tabelas e relacionamentos.

Para arquivos em geral, tanto gerado pelo aplicativo quanto para os download, podemos utilizar o Internal/External Storage. Interno salvará o arquivo na memória interna, enquanto que o Externo salvará em um cartão de memória. Aliás, esse foi o meu primeiro registro sobre programação Android, então vou ter que dar uma revisada neste ponto.

Por último, podemos salvar os dados na nuvem, Google Drive, Firebase, etc...


Como utilizar o Shared Preferences
Como dito antes, Shared Preferences possui uma estrutura de Chave/Valor, por isso, ele é ótimo para armazenar informações com uma semântica simples, por exemplo:

Nome = "João"
CorCamisa = "Verde"
CorBermuda = "Azul"
CorFundo = "Vermelho"

Acredito que deu para entender.

1. PreferenceFragment
Então, a primeira coisa que precisamos fazer é criar um PreferenceFragment, que é uma interface para nós modificar um Shared Preference. Não é exatamente necessário criar um, mas como é comum utilizar uma tela de configurações, então o PreferenceFragment já auxilia nesta tarefa.

Então, para nós criar, primeiro temos que criar uma depêndencia no arquivo do Gradle:

dependencies{
    compile 'com.android.support:preference-v7:25.0.0'
}

Em seguida, criaremos uma classe que herda da classe PreferenceFragment ou PreferenceFragmentCompat. Também implemente as classes que o Android Studio irá pedir para implementar. A classe ficará com esse template:

public class NomeDaClasse extends PreferenceFragmentCompat{
  
  @Override
  public void onCreatePreferences(Bundle savedInstanceState, String rootKey){
     
  }
}

2. Criando o Arquivo de Preferências
Com o botão direito do mouse, vá em "New > Directory" e crie um diretório chamado xml (isso se ela já não existir). Então, clique na pasta com botão direito, vá em "New > XML Resource File". Dê um nome. O arquivo XML de preferência sempre terá como nó raiz a tag <PreferenceScreen>.
Dentro da mesma, você vai determinar os elementos e como será a interface, como:

  • CheckBoxPreference: Configura a opção como Checkbox;
  • ListPreference: configura a opção com uma lista para selecionar
  • EditTextPreference: configura em um campo de texto

Exemplo de como pode ser o XML:
<?xml version="1.0" encoding="UTF-8" ?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
  <CheckBoxPreference
    android:defaultValue="true"
    android:key="show_bass"
    android:summaryOff="Hidden"
    android:summaryOn="Shown"
    android:title="Show Bass" />
  <ListPreference
    android:defaultValue="Valor default"
    android:entries="@array/opcoes"
    android:key="list_array"
    android:title="Array List" />
</PreferenceScreen>

3. Implementar onCreatePreferences
Aqui vamos implementar o método onCreatePreferences com base no arquivo XML

@Override
  public void onCreatePreferences(Bundle savedInstanceState, String rootKey){
     addPreferencesFromResource(R.xml.nome_xml);
  }

4. Adicionar o Fragmento na Activity
Aqui vamos usar inserir o fragmento na Activity (não entrarei agora na questão fragmento, mas veremos futuramente). No arquivo de layout da Activity, colocaremos como base, a tag fragment. Ficará assim:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/activity_settings"
   android:name="android.example.com.visualizerpreferences.NomeDaClasse"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />


Lendo um valor de Preferences
Para ler uma Preferences, você pode requisitar para PreferencesManager um acesso para as Preferences. Para isso, em algum lugar que a Activity esteja em execução, podemos invocar o um método para obeter a preferencias e usá-los para obter um valor, de forma muito semelhante a um Bundle, exceto que ele pede um segundo parâmetro que seria um valor padrão:

public void NomeActivity extends Activity{
   [...]

   public void pref(){
      SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
      int chave1 = sharedPref.getInt("chave1", 0);        
   }
}

Escrevendo um valor nas Preferences (Sem usar PreferenceFragment)
De forma bastante similar ao código anterior, mas usaremos um Editor para poder inserir um valor:


   public void prefEdit(){
      SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
      SharedPreferences.Editor editor =  sharedPref.edit();        
      editor.putInt("chave1",1);
      editor.apply();
   }


Atualizando a Activity sobre mudanças na Shared Preferences: onSharedPreferenceChangeListener
Um dos casos do SharedPreferences é que muitas vezes as opções que você alterou deve fazer efeito imediatamente, entretanto, o SharedPreferences é invisível para a Activity. Para isso precisamos implementar um Listener para ser notificado de alguma mudança.

1. Na Activity, implementar a interface onSharedPreferenceChangeListener

public void NomeActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener{
   
  @Override
  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
    //Implementar aqui o que vai mudar, geralmente baseado
    //na key
  }  

}

2. Registrar o Listener

public void NomeActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener{
    public void registerListener(){
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPref.registerOnSharedPreferenceChangeListener(this);

    }   

}

3. Remover o Listener quando a Activity for destruído:

public void NomeActivity extends Activity implements SharedPreferences.OnSharedPreferenceChangeListener{
    
   @Override
   protected void onDestroy(){
     super.onDestroy();
     PreferenceManager.getDefaultSharedPreferences(this)
         .unregisterOnSharedPreferenceChangeListener(this);
   }
}


Resumo Rápido de outras funcionalidades:


  • Em Preferences de campo de texto, você pode usar o listener PreferenceChangeListener para validar o texto e impedir que um dado inválido seja gravado;

Nenhum comentário:

Postar um comentário