DESENVOLVER PARA ANDROID: PERSISTÊNCIA COM SQLite (Finalizando).

Para que tudo que nós fizemos faça sentido, é preciso que possamos adicionar os registros no banco e com isso, alterar o nosso formulário para a criação do registro Pessoa, e criar um evento no botão inserir funcione.

Primeiro, temos que substituir o hardcoded por uma chamada ao PessoaDAO e alterar o ArrayAdapter para receber nossa lista de Pessoas.

Depois, vamos substituir o código do botão por algo que realmente funcione. Então pegaremos os dados da tela, preencheremos o objeto Pessoa e diremos ao PessoaDAO que o salve.

E agora é testar. Ai vai o código.


public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.lista);
      lista = (ListView) findViewById(R.id.lista);

     PessoaDao dao = new PessoaDao(this);
      List<Pessoa> pessoas = dao.getLista();
      dao.close();

      ArrayAdapter<Pessoa> adapter = new ArrayAdapter<Pessoa>(this,android.R.layout.simple_list_item_1,pessoas);
      lista.setAdapter(adapter);
      lista.setClickable(true);
}

Button botao = (Button) findViewById(R.id.botao);
botao.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
EditText nome = (EditText) findViewById(R.id.EditNome);
EditText telefone = (EditText) findViewById(R.id.editTelefone);
EditText site = (EditText) findViewById(R.id.editSite);
EditText endereco = (EditText) findViewById(R.id.editEndereco);

pessoa.setNome(nome.getEditableText().toString());
pessoa.setTelefone(telefone.getEditableText().toString());
pessoa.setSite(site.getEditableText().toString());
pessoa.setEndereco(endereco.getEditableText().toString());

PessoaDao dao = new PessoaDao(Formulario.this);

if(posicao != -1){
    pessoa.setId(posicao+1);
    dao.alterar(pessoa);
 }else{
    dao.inserir(pessoa);
 }
dao.close();

finish();
}
});

Um ponto importante, é se você deixar desta maneira, a app vai começar a empilhar telas, então vamos usar.

Quando chamamos o método finish, ele finaliza a Activity que está em primeiro plano, e ao voltar na anterior ele roda o método onRestart() (Ver ciclo de vida das Activity’s). Então vamos implementar o onRestart na Activity principal.


@Override
protected void onResume() {
     super.onResume();
     carregaLista();
}

private void carregaLista() {
     PessoaDao dao = new PessoaDao(this);
     List<Pessoa> pessoas = dao.getLista();
     dao.close();

     lista.setAdapter(new ArrayAdapter<View>(this, android.R.layout.simple_list_item_1,pessoas){
}

Quando eu já estiver inserido algum registro, o botão que será renderizado ao clicar em um item na tela de listagem será o botão de update de pessoa. Então acesse o menu “novo” e veja o resultado.Ao final de tudo, o resultado será esse.

47 Responses to DESENVOLVER PARA ANDROID: PERSISTÊNCIA COM SQLite (Finalizando).

  1. esme123 says:

    podrias facilitarme el codigo fuente de este ejemplo porfavor????

  2. esme123 says:

    pq aparece la clase Alumno???

  3. esme123 says:

    poderia facilitar o código de persistência no Android, a gestão SQLite?
    muito obrigado

  4. Renato Lage says:

    Aê.. poderia postar o fonte completo? estou tentando aprender a programar em android, mas ta osso… gostei desse seu exemplo.. super bem explicado… gostaria do fonte para estudar melhor…
    Grato

  5. Daniel de Cesaro says:

    Yuri,
    Muito bacana o post, parabéns.

    Teria como ver o link do fonte, pois não está OK ?

    Obrigado

  6. Daniel de Cesaro says:

    Yuri,

    Desculpe, mas não vi o ponto. Está tudo OK.

    Mais uma vez, parabéns pelo post.

    Obrigado!

  7. Estou com duas dúvidas:

    A primeira. Toda vez que eu chamar “PessoaDao dao = new PessoaDao(Formulario.this);”, ele não irá sobrescrever o banco caso eu chame mais de uma vez?

    A Segunda, eu teria que criar um DAO para cada tabela?

    Obrigado,
    ChristianG.

    • Yuri Adams says:

      E ai Christian. Cara sim, toda vez que eu fizer o deploy no emulador ou no mobile, ele irá apagar o banco e criar de novo.
      MAs eu fiz isso só pelo exemplo simplório.
      E a segunda pergunta, depende da prática que vc tá fazendo. Eu prefiro sempre ter uma “entidade” que represente minha tabela no banco. Mas depende de cada um.
      Abraço, qualquer coisa estamos ai

  8. Fabiano Almeida says:

    Cara muito obrigado pelo post.

    Está me ajudando muito.

    Só não entendi uma coisa.

    Onde está a parte que vc cria o banco?

    Não estou encontrando o nome do banco no seu exemplo.

    Não teria que ter um DataBaseCreate?

    Aguardo retorno.

    Valeu pela força cara

    • Yuri Adams says:

      Fala Fabiano, tudo tranquilo?

      Cara o código pra gerar o banco está na primeira parte dos posts sobre SQLite.
      Quando você sobrescreve o método onCreate da classe SQLiteOpenHelper, você insere o script SQL nele. Segue:

      @Override
      public void onCreate(SQLiteDatabase db) {
      String sql = “CREATE TABLE ” + TABELA +
      “( id INTEGER PRIMARY KEY,” +
      ” nome TEXT UNIQUE NOT NULL,” +
      ” telefone TEXT,” +
      ” endereco TEXT,” +
      ” site TEXT, ” +
      ” foto TEXT” +
      “);”;
      db.execSQL(sql);
      }

      O nome das tabelas e do schema está descrito nestas constantes. Assim você pode personalizar ao seu caso.

      Abração

  9. Fabiano Almeida says:

    Amigo muito obrigado mesmo.

    Isto me ajudou muito.

    Preciso tirar só mais uma dúvida com vc.

    Quando o banco for atualizado os dados serão perdidos certo?

    Existe alguma forma de impedir isto?

    Grande abraço.

  10. Amigo poderia me dizer como eu consigo passar as informações gravadas no formulario para um arquivo txt, ou então onde posso acessar es arquivos de dados posteriormente mas fora do sistema Android?
    obrigado.

    Abraço!

    • Yuri Adams says:

      Opa amigo, desculpe a demora.

      Cara seguinte, os dados preenchidos no formulário podem ser pegos dessa forma:
      EditText nomeDoCampo = (EditText) findViewById(R.id.idMapeadoNoRJava);
      nomeDoCampo.getEditableText().toString();

      Dessa forma você captura a string do campo de input.

      Tendo essa String, vc manipula como sua preferência, coloca no banco de dados, arquivo txt.

      Espero ter ajudado. Abraços

  11. Amigo gostaria de te aprabenizar pelos post, estou estudando a linguagem e o blog esta me ajudando muito.

    No entanto estou com problemas para inserir e selecionar valores do banco, creio que esteja certo minha classe modelo, mas não com a DAO.
    Em que trecho do código é criado o banco de dados?
    O erro diz que houve uma parada inesperada…
    Se puder me ajudar fico agradecido,
    Abs

  12. Caro Yuri, consegui resolver, era apenas um campo do banco de dados que estava diferente da classe DAO.
    Obrigado, e parabens mais uma vez!

  13. Cara desculpa te torrar de novo..
    consegui inserir os dados de boa, agra estou com um problema,
    na hora da select não esta trazendo exatamente os valores do BD,
    faz a select, mas ao invez dos valores traz o nome do pacote “@” alguns numeros…
    o que pode ser isso? em algum momento é necessario converter a List em String?
    Abs

  14. Amigo estou tentando mostrar o resultado da consulta numa List mas sem sucesso…
    Aparece o nome do pacote @ numeros na list, com a mesma quantidade de registros no banco.

    Chamada do metódo e exibição na list
    ————————————————————————————————————————-
    PedidoVendaDAO dao = new PedidoVendaDAO(this);
    List pedvenda = dao.getLista();
    dao.close();

    ArrayAdapter adapter = new
    ArrayAdapter(this,android.R.layout.simple_list_item_1,pedvenda);

    lstPdv.setAdapter(adapter);
    lstPdv.setClickable(true);
    ————————————————————————————————————————-

    DAO
    ————————————————————————————————————————-
    public List getLista(){
    Cursor c = getWritableDatabase().query(TABELA, COLUNAS, null, null, null, null, null);
    List lista = new ArrayList();
    PedidoVenda pdv = new PedidoVenda();
    while(c.moveToNext()){
    pdv.setCodigo(c.getInt(0));
    pdv.setProduto(c.getString(1));
    pdv.setData(c.getString(2));
    pdv.setQuantidade(c.getString(3));
    pdv.setCliente(c.getString(4));

    lista.add(pdv);
    Log.i(pdv.toString(), lista.toString());
    }
    c.close();

    return lista;

    }
    ————————————————————————————————————————-
    Reultado uma list:

    br.com.PedidoVenda@4396c958
    br.com.PedidoVenda@4396cc00
    br.com.PedidoVenda@4396cd48
    br.com.PedidoVenda@4396ce80

    Os quatro registros do banco aparecem assim, mas é uma tabela de 5 campos.
    poderia me ajudar?
    Abraço!

    • Yuri Adams says:

      Ola Maurilio,

      Que é isso cara, você está torrando nada não, fique a vontade de perguntar.

      Seguinte, Dessa forma vc está trazendo os registros no banco. Por ai tudo bem,

      Acho que você olhou no debug, e a consulta está trazendo oq é pra estar trazendo.

      Ok, trazendo estes dados, você tem que personalizar a tela para que exiba os labels direitos, blz?

      Infelizmente agora agora eu não posso mandar um código de exemplo, mas pesquisa algo relacionado do LayoutInflater ok?

      Mais tarde eu posto um exemplo.

      Abraços Maurilio e obrigado pelo elogio.

      • Valew Yuri, vou pesquisar, fico na espera do exemplo então,
        se eu consegui antes eu posto aqui, Abraço!

      • Yuri Adams says:

        cara, o método que eu to mandando ele tem mais que o que vc quer.. Mas acho que tu extraindo o que é o do seu interesse dá certo…

        private void carregaLista() {
        AlunoDao dao = new AlunoDao(this);
        List alunos = dao.getLista();
        dao.close();

        LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final List linhas = new ArrayList();

        for(int i = 0; i< alunos.size(); i++){
        Aluno aluno = alunos.get(i);
        View view = vi.inflate(R.layout.item, null);

        LinearLayout ll = (LinearLayout) view.findViewById(R.id.fundo);
        if(i%2 == 0){
        ll.setBackgroundColor(0xFFDDEEFF);
        }else{
        ll.setBackgroundColor(0xFFF0F0F0);
        }

        ImageView imagem = (ImageView) view.findViewById(R.id.foto);

        if(aluno.getFoto() == null){
        imagem.setImageResource(R.drawable.noimage);
        }else{
        try{
        FileInputStream stream = new FileInputStream(aluno.getFoto());
        Bitmap bmp = BitmapFactory.decodeStream(stream);
        stream.close();
        imagem.setImageBitmap(bmp);
        }catch (IOException e) {
        e.printStackTrace();
        }
        }

        TextView texto = (TextView) view.findViewById(R.id.texto);
        texto.setText(aluno.getNome());
        texto.setTextColor(Color.BLACK);

        linhas.add(view);
        }

        lista.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1,linhas){
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
        return linhas.get(position)/*super.getView(position, convertView, parent)*/;
        }
        });

        }

        Ele muda o background da tela, seta uma foto, altera a cor do texto.. Essas coisas..

        Qualquer dúvida estamos aqui..

      • Raphael Nunes says:

        Cara, essa resposta que você postou aqui, não funcionou comigo. É o seguinte. Acontece a mesma coisa comigo, ao invés de aparecer o nome está aparecendo o nomedopacote.activity@4238
        Aí eu vi aqui nos comentários, mas não funcionou comigo, E além de mostrar o nome, eu preciso obter o id que já está dentro do objeto e mandar para outra activity.
        Tem como dar uma força? Valeu.

  15. Yuri, obrigado pela resposta, desde a hra do post estou tentando mas ainda não deu certo…
    cara no trecho <<>> o item é a ListView do xml certo?

    ta dando pau no setAdapter…

    consegui fazer uma lista mas com spinne e sem interação com banco.
    qdo consegui fazer com persistencia de dados ou se for util me fala que eu te mando os códigos…

    Vlw pela ajuda!

  16. Desculpe, no trecho R.layout.item, o item é o componente ListView do xml?
    mais uma dúvida, de onde surgiu o
    lista.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1,linhas);

    de onde vem o lista?
    Desculpe se a dúvida é meio tosca, estou começando a programar nessa linguagem…mas estou fascinado com ela.

    vlw mano

  17. Yuri tentei com o LayouInflater mas retornava a tela vazia, como se linhas.add(view) não funcionasse, se lá..mas descolei de um outro jeito, só que bem pior, retornando os dados em TextView, pra falar bem a verdade fica uma bos**, mas é o jeito…vlw pelas dicas, continuo seguindo teu blog, e parabens novamente…Abs

    • Yuri Adams says:

      To ligado cara, qualquer solução que eu lembre eu ti envio.. E obrigado pelos comentários.. Abração!

  18. Cara, muito obrigado, foi nesses posts que finalmente eu entendi como é que funciona uma persistência. Isso nunca entrava na minha mente. Nem tanto pelo android, mas aprendi os dois ao mesmo tempo, tanto o conceito de persistência como uso de android com banco de dados.

    Abraços.

  19. Yuri, o problema estava na classe modelo
    eu estava retornando o objeto em si, mas na verdade precisava “converte-lo” em String

    foi só colocar no final da classe

    public String toString(){
    return this.Produto; // Atributos da classe
    }

    que retornou os valores corretos.

    Cara, muito obrigado pela ajuda, até mais,
    boa sorte, Abs

  20. @ Raphael Nunes

    Cara, o Yuri me ajudou muito nesse blog, inclusive nesse problema, conseguimos resolver da seguinte maneira…

    sobrescrevendo o metodo toString()

    public class PedidoVenda {
    String Atributo;

    // getters and setters

    public String toString(){
    return this.Atributo; // Isso faz com que retorne uma string completa
    }
    }

    mano, em relação para pegar o id tenta ai

    ClasseModelo modelo = lista.get(position);

    modelo.getId() // Atributos conforme get e set

    Abs, boa sorte

    Vlw Yuri

    • Raphael Nunes says:

      Cara, muito obrigado, mas não consegui fazer, teria algum exemplo mais prático. Por exemplo depois onde eu chamo o toString()?

      Referente ao texto.

      public void AtualizarLista(){
      PessoaDao pessoaDao = new PessoaDao(this.ctx);
      lista = (ListView) view.findViewById(R.id.lista);

      List pessoas = pessoaDao.getLista();

      ArrayAdapter adapter = new ArrayAdapter(this.ctx, android.R.layout.simple_list_item_1, pessoas);
      lista.setAdapter(adapter);
      lista.setClickable(true);

      }

      Valeu.

      • Vc esta tentando recuperar dados do banco de dados certo?
        tente assim p ver se funciona…

        public void AtualizarLista(){
        PessoaDao pessoaDao = new PessoaDao(this.ctx);
        lista = (ListView) view.findViewById(R.id.lista);

        List pessoas = pessoaDao.getLista();

        ArrayAdapter adapter = new
        ArrayAdapter(this,android.R.layout.simple_list_item_1, pessoas);

        lista.setAdapter(adapter);
        lista.setClickable(true);
        }

      • Raphael Nunes says:

        Não funciona cara, assim ele retorna só a identificação do objeto package.applicacao@2442, ele não retorna o texto. Onde eu chamo aquele toString() que eu sobescrevi?

  21. Tenta coloca isso no fim da sua classe modelo retornando todos seus atributos.

    public String toString(){
    return this.Atributo; // Isso faz com que retorne uma string completa
    }

    • Yuri Adams says:

      Fala Galera,
      Raphael, a saida é como o Murillo e eu estavamos discutindo anteriormente.
      Quando vc sobrescreve o toString() na sua classe de modelo. Toda vez que seu objeto da sua classe de modelo for chamada, o toString() será chamado e então será exibido o que vc quer que seja exibido :).. Então tenta o que o Murillo falou..
      Sobrescreva o toString() na sua classe de modelo, e na sua Activity faz o normal, faz um adapter pra aquela lista de objetos e rode a app pra ver se deu certo. É pra dar certo.. 🙂

      Vlw pelos comentários “Negada”!

      • Raphael Nunes says:

        AAAAAAHHH. Agora deu certo. Valeu @Yuri e @maurilionovais. Funcionou certinho. Mas só não entendi direito o porquê. Porquê o método toString em nenhum momento é chamado tanto no objeto pessoa, quanto na activity. Mas mesmo assim muito obrigado, nem sabia que dava pra sobreescrever um método.

      • Rafael pelo que eu entendi é que quando se exibe mostra o objeto em si, e quando usa o
        toString, acessa o conteudo que está no objeto.

        éNozes!!
        Abs Yuri e Rafael

      • Raphael Nunes says:

        Ah, valeu, acho que deu pra entender.

        Abraços. Vocês são fera.

      • Yuri Adams says:

        Raphael, o método toString() que é da classe Object, classe pai de todos os objetos no java, serve para a apresentação do objeto que aquele método é implementado.
        Então se na sua classe Pessoa.java vc define seu método toString() como:

        public String toString(){
        String retorno = nome + “” + sobrenome;
        }

        Toda vez que o objeto for exibido, ele será mostrado como nome mais o sobrenome da classe. Deu pra entender?
        Ele é chamado por debaixo dos panos quando vc exibe uma lista desses objetos na Activity. Mas o toString() funciona também quando vc vai debuggar seu código, ao invés de aparecer o endereço dele de memória, vai ser mostrado o toString() dele..

        Se quiser que eu explique de novo é só falar. 🙂

        Abração

      • Raphael Nunes says:

        Ah, agora entendi melhor ainda. Valeu, gostei da ideias tbm de debugar o código, parece ser uma boa.

        Abraços. Falou.

  22. Carlos H Marian says:

    Olá…
    em que momento eu defino o nome do meu banco de dados?
    Obrigado.

    • Yuri Adams says:

      @Override
      public void onCreate(SQLiteDatabase db) {
      String sql = “CREATE TABLE ” + nomeDaTabela +
      “( id INTEGER PRIMARY KEY,” +
      ” nome TEXT UNIQUE NOT NULL,” +
      ” telefone TEXT,” +
      ” endereco TEXT,” +
      ” site TEXT, ” +
      ” foto TEXT” +
      “);”;
      db.execSQL(sql);
      }
      Nesse Momento vc vai criar seu Banco de Dados e alterar o nome do mesmo, onde tem “nomeDaTabela”

      Abraços..

Deixar mensagem para Daniel de Cesaro Cancelar resposta