Camada das Funções
A primeira camada que vamos criar corresponde as funções que necessitamos. No caso deste projeto, funções de tratamento com Datas. Criamos uma nova classe no pacote projeto.livro.faltam chamada UtilData com a seguinte codificação:public class UtilData { private static Date dataAtual = new Date(); private static String formatarData(final Date data) { DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.UK); return sdf.format(data); } private static Date strToDate(final String dataStr) { DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.UK); try { return sdf.parse(dataStr); } catch (Exception e) { Log.e("Faltam", "Erro na data: " + e.getMessage()); } return null; } public static Date convDiaMesToDate(final String diaMes) { Calendar original = new GregorianCalendar(); original.setTime(dataAtual); int anoAtual = original.get(Calendar.YEAR); String montaData = diaMes.substring(0, 2) + "/" + diaMes.substring(2) + "/" + anoAtual; return strToDate(montaData); } public static Date convDiaToDate(final String dia) { Calendar original = new GregorianCalendar(); original.setTime(dataAtual); int diaAtual = original.get(Calendar.DAY_OF_MONTH); int mesAtual = original.get(Calendar.MONTH); int anoAtual = original.get(Calendar.YEAR); if (diaAtual > Integer.parseInt(dia)) { mesAtual++; if (mesAtual > 11) { mesAtual = 0; anoAtual++; } } mesAtual++; String montaData = dia + "/" + ((mesAtual < 10) ? "0" + mesAtual : mesAtual) + "/" + anoAtual; return strToDate(montaData); } public static String retornarDiferencaComAtual(final Date dataOri) { // Data é hoje if (formatarData(dataAtual).equals(formatarData(dataOri))) { return "É hoje"; } Calendar diaCirc = new GregorianCalendar(); diaCirc.setTime(dataAtual); int dia = 0; while (!formatarData(diaCirc.getTime()).equals(formatarData(dataOri))) { diaCirc.add(Calendar.DAY_OF_MONTH, 1); dia++; } return dia + (dia > 2 ? " dias" : " dia"); } }Os métodos desta classe são:
- formatarData(final Date data): converter um objeto do tipo Date para um objeto tipo String no formato DD/MM/AAAA.
- strToDate(final String dataStr): converter um objeto tipo String no formato DD/MM/AAAA para um objeto tipo Date.
- convDiaMesToDate(final String diaMes): converter um objeto tipo String no formato DDMM (Dia e Mês) para um objeto tipo Date.
- convDiaToDate(final String dia): converter um objeto tipo String no formato DD (Dia) para um objeto tipo Date. Se o dia informado for menor que o dia atual o mês será o atual, caso contrário o mês será o seguinte.
- retornarDiferencaComAtual(final Date dataOri): retornar quantos dias faltam para chegar até o dia atual, recomenda-se que este método seja utilizado somente para períodos de um ano.
Java trata objetos tipo Date com duas classes: Calendar e GregorianCalendar. Se observamos veremos que todos os métodos contidos na própria Date estão depreciados, então usamos basicamente essas duas classes para lidar com esse tipo de objeto. Já as conversões para o tipo String são tratadas pela classe: SimpleDateFormat.
Camada de Dados
Precisamos realizar uma pequena modificação no método toString() da classe Registro, modificá-lo para a seguinte codificação:@Override public String toString() { if (dia.length() == 2) { return descricao + ": " + UtilData.retornarDiferencaComAtual(UtilData.convDiaToDate(dia)); } else { return descricao + ": " + UtilData.retornarDiferencaComAtual(UtilData.convDiaMesToDate(dia)); } }Agora a diferença de dias já pode ser visualizada sem problemas na lista.
Uma boa prática é separar os métodos de Gravação e Leitura de arquivo e isolá-los em uma nova classe no pacote projeto.livro.faltam chamada UtilArquivo com a seguinte codificação:
public class UtilArquivo { protected static void carregarLista(final List<registro> lista, final FileInputStream arquivo) throws Exception { ObjectInputStream ois = null; try { ois = new ObjectInputStream(arquivo); Registro reg; do { reg = (Registro) ois.readObject(); lista.add(reg); } while (true); } catch (EOFException e) { } finally { ois.close(); } } protected static void gravarLista(final List<registro> lista, final FileOutputStream arquivo) throws Exception { ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(arquivo); for (Registro regs : lista) { oos.writeObject(regs); oos.flush(); } } finally { oos.close(); } } }São os mesmos métodos que já vimos na postagem anterior. Isolados aqui, foram mais simplificados, ou seja, o método carregarLista() carrega todos os objetos do arquivo para a lista, enquanto que o método gravarLista() grava todos os objetos da lista para o arquivo.
Atividade Principal
Para finalizarmos nosso aplicativo, procederemos mudanças na classe MainActivity:public class MainActivity extends ListActivity { private EditText edDescricao; private EditText edDia; private final List<registro> lista = new ArrayList<registro>(); private ListView listaRegs; private void eliminarRegistro() { for (int i = listaRegs.getCount(); i > -1; i--) { if (listaRegs.isItemChecked(i)) { lista.remove(i); } } mostrarLista(); } private void guardarRegistro() { lista.add(new Registro(edDescricao.getText().toString(), edDia.getText() .toString())); mostrarLista(); edDescricao.setText(""); edDia.setText(""); edDescricao.requestFocus(); } private void mostrarLista() { ArrayAdapterVamos começar pelo método onCreate() que é chamado assim que o aplicativo é iniciado, a lista da tela é associada a um objeto do tipo ListView, sua visão também foi modificada permitindo que o usuário possa selecionar os registros que deseja excluir. Através do ciclo de vida o próximo método chamado é o onStart() que será responsável por carregar a lista do arquivo texto, e esta lista agora só será gravada quando o método onStop() for chamado (assim evitamos I/O desnecessários). O método mostrarLista() procede a atualização da lista na tela (devemos lembrar que estamos trabalhando com dois objetos o ListView e um List que não estão sincronizados).adaptador = new ArrayAdapter (this, android.R.layout.simple_list_item_checked, lista); listaRegs.setAdapter(adaptador); } @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); edDescricao = (EditText) findViewById(R.id.descricao); edDia = (EditText) findViewById(R.id.dia); listaRegs = getListView(); listaRegs.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); findViewById(R.id.guardar).setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { guardarRegistro(); } }); findViewById(R.id.eliminar).setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { eliminarRegistro(); } }); } @Override protected void onStart() { super.onStart(); try { UtilArquivo.carregarLista(lista, openFileInput("dias.reg")); } catch (Exception e) { Log.e("Faltam", "Erro Leitura: " + e.getMessage()); } mostrarLista(); } @Override protected void onStop() { super.onStop(); try { UtilArquivo.gravarLista(lista, openFileOutput("dias.reg", Context.MODE_PRIVATE)); } catch (Exception e) { Log.e("Faltam", "Erro Leitura: " + e.getMessage()); } } }
Finalmente os dois métodos responsáveis pelas ações de Gravar e Eliminar os registros da lista através do pressionamento dos botões pelo usuário. O método guardarRegistro() adiciona um novo registro a lista e o método eliminarRegistro() verifica qual registro da lista foi selecionado pelo usuário e procede sua retirada (observe que o laço anda de trás para frente eliminando os registros, isso é feito pois tudo é posicional).
Pronto, podemos rodar sem problemas nosso projeto e inclusive passá-lo para o celular (não esqueça da diretiva android:installLocation=”auto” que permitirá que a aplicação seja colocada no cartão de memória.
Utilize este projeto para descobrir como:
- Realizar gravações de objetos em arquivos;
- Realizar a leitura de objetos em arquivos;
- Utilizar o objeto tipo Date e suas conversões para o tipo String;
- Utilizar lista com marcadores tipo Check;
- Incluir e eliminar dinamicamente registros em listas.
Fernando Anselmo
0 comentários:
Postar um comentário