Capítulo 10. Adicionando persistência

     O mecanismo persistência que está sendo usado é baseado em "RecordStore". O "RecordStore" tem um nome atribuído a ele - algo como escolher para sua aplicação que não um "clash" com algum outro. Chamará "MileageCalcStore". Os registros dentro de "RecordStore" têm um índice numérico, e são simplesmente "byte array"

     Adicione dois métodos novos a sua classe: "saveCurrentState()" e "loadCurrentState()". Para ser breve, inclua simplesmente o código aqui, conforme descrito abaixo:

public void saveCurrentState() {
   RecordStore myStore = null;
   try {
      myStore = RecordStore.openRecordStore("MileageCalcStore", true);
      int n = myStore.getNumRecords();

      // crie as respresentações de "byte array" para armazenar
      byte[] startingMileageBytes =  Long.toString(this.startingMileageVal).getBytes();
      byte[] currentMileageBytes =   Long.toString(this.currentMileageVal).getBytes();
      byte[] totalFuelBytes =  Long.toString(this.totalFuelVal).getBytes();
      byte[] totalCostBytes =  Long.toString(this.totalCostVal).getBytes();

      // Temos já um conjunto de registros para usar?
     if (n == 0) {
         // não - crie novos registros
         myStore.addRecord(startingMileageBytes, 0, startingMileageBytes.length);
         myStore.addRecord(currentMileageBytes, 0, currentMileageBytes.length);
         myStore.addRecord(totalFuelBytes, 0, totalFuelBytes.length);
         myStore.addRecord(totalCostBytes, 0, totalCostBytes.length);
      }
      else {
         // use registros existentes
         myStore.setRecord(1, startingMileageBytes, 0, startingMileageBytes.length);
         myStore.setRecord(2, currentMileageBytes, 0, currentMileageBytes.length);
         myStore.setRecord(3, totalFuelBytes, 0, totalFuelBytes.length);
         myStore.setRecord(4, totalCostBytes, 0, totalCostBytes.length);
      }
   }
   catch(Exception ex) {
      // omitido por breve - mas deve fazer algo com isto
   }
   finally {
      if(myStore != null) { 

try {
            myStore.closeRecordStore();
        }

catch(Exception ex) {           

// ignore
        }
      }
   }
}

     Algumas notas :
  • O "true" quando aberto o "Record Store" indica que um "store" deve ser criado pelo nome, se ainda não existir.
  • Sem dúvida, existem melhores maneiras de conseguir um "byte array" de valores. Este é um rápido exemplo e conversão para "string" e então manter os "bytes" em algo agradável, limpo e fazendo algo fácil para carregar também para o "debug", mas sentem-se livres para executar o armazenamento e a recuperação em seu próprio estilo.
  • Estará armazenando somente os totais e o início da milhagem; tudo mais será calculado na carga.
  • Ao criar novos registros, utilize o "addRecord" (e o número do índice incrementará automaticamente); quando existir algum reúso, o número do índice é o primeiro argumento.
  • Lembre de adicionar alguns "includes" necessários para conseguir compilar isto (como "RecordStore"). Clique no botão direto e "Fix Imports."
  • Finalmente, o bloco é importante para fechar o conjunto de registros, se nada estiver errado.  Deverá sempre incluir o bloco final para limpar algo que esteja pendendo no conjunto de registros.

     Agora, precisará também do código para carregar os valores de volta:

public void loadCurrentState() {
RecordStore myStore = null;
try {
myStore = RecordStore.openRecordStore("MileageCalcStore", true);
int n = myStore.getNumRecords();
if(n == 0) {

// se não tiver um conjunto de registros, sue valores seguros
this.startingMileageVal = 0;
this.currentMileageVal = 0;
this.totalFuelVal = 0;
this.totalCostVal = 0;
}
else {
String startMile, currentMile, totCost, totFuel;
startMile = new String(myStore.getRecord(1));
currentMile = new String(myStore.getRecord(2));
totFuel = new String(myStore.getRecord(3));
totCost = new String(myStore.getRecord(4));

// agora analise a saída dos valores
this.startingMileageVal = Long.parseLong(startMile);
this.currentMileageVal = Long.parseLong(currentMile);
this.totalMileageVal = currentMileageVal - startingMileageVal;
this.totalFuelVal = Long.parseLong(totFuel);
this.totalCostVal = Long.parseLong(totCost);
}
}

catch(Exception ex) {
// TODO: faça algo como excessão (omitido por breve)
}
finally {
if(myStore != null) {
try {
myStore.closeRecordStore();
}

catch(Exception ex) {

// ignore
}
}
}
// agora atualize as médias e sumario
this.recalcAveragesAndUpdateSummary();
}

     Este código deve fazer sentido se compreender o código "store"; é basicamente uma reversão da funcionalidade de "store". "Strings" são reconstruídas de "bytes arrays" e então são analisadas gramaticalmente dentro de "longs". Finalmente, as médias e o método sumário de "update" são invocados, para conseguir tudo na  sincronização.

     Assim, agora terá os métodos para salvar e carregar os dados, mas não será chamado em qualquer lugar. Poderia escolher chamar o método "save" sempre que   inicializar ou adicionar detalhes em métodos que serão usados, e carregar no "startup". Usualmente escolhe-se colocar o método "save" ao invés dos métodos de ciclo de vida "pauseApp" e "destroyApp":

  1. Localizar os métodos "startApp()", e depois o "initialize()";  chamar e adicionar "this.loadCurrentState()";
  2. Localize os métodos "pauseApp()" e "destroyApp"("boolean" incondicional) e em ambos adicionar a linha:
    this.saveCurrentState();

     Salvar e eliminar erros da aplicação outra vez. Desta vez quando rodar, poderá sair da aplicação (no emulador do telefone) e então reiniciá-la outra vez, e seus totais e   médias atuais devem ainda estar lá. Note que se realmente fechar o emulador e o reiniciar, seus números serão perdidos; mas o principal é que armazenará                     permanentemente no dispositivo.