Consulta em listas

Pessoal, gostaria de um pequeno auxílio:

Gostaria de saber como eu faço para uma informação que cadastrei no banco SQLite seja exibida numa ListView em uma outra activity?

Eu estava olhando esse exemplo:

Mas eu estou um pouco confuso com algumas coisas como o DataSource e o SimpleCursorAdapter.

Alguém poderia me auxiliar com um exemplo mais simples?

Obrigado

Me fala aonde exatamente está sua dúvida. Pois o exemplo que você passou está completo.

Se for sobre o adapter: http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html

[code] dataSource = new SimpleCursorAdapter(this, R.layout.row, contatos,
campos, new int[] { R.id.tvNome, R.id.tvEndereco , R.id.tvTelefone });

        //relaciona o dataSource ao próprio listview
        listView.setAdapter(dataSource);[/code]

Minha dúvida está nessa parte. Porque a tela row é referenciada no SimPleCursorAdapter? E essas variáveis tvNome,tvEndereco, o que são?

Da documentacao, o construtor:

[quote]Parameters
context The context where the ListView associated with this SimpleListItemFactory is running
layout resource identifier of a layout file that defines the views for this list item. The layout file should include at least those named views defined in "to"
c The database cursor. Can be null if the cursor is not available yet.
from A list of column names representing the data to bind to the UI. Can be null if the cursor is not available yet.
to The views that should display column in the “from” parameter. These should all be TextViews. The first N views in this list are given the values of the first N columns in the from parameter. Can be null if the cursor is not available yet.
flags Flags used to determine the behavior of the adapter, as per CursorAdapter(Context, Cursor, int).[/quote]

Da uma olhada no exemplo o layout em xml. Lá mostra os detalhes dos textViews:

<TextView android:id="@+id/tvNome" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Nome" android:layout_alignParentLeft="true"/>

Então, o R.id.tvNome, é a referência ao TextView

Isso eu entendi, mas porque ela é referenciada na parte de consultas? Porque eu penso assim: você insere informações no Banco, quando faço uma consulta, essa consulta retornará para uma listView aquilo que estiver armazenado, certo? O que faz esse tvNome se ela é só uma label?

Cara, você não entendeu ainda.

O simpleCursorAdapter, pega um layout, o seu cursor, as colunas que você deseja (passa por String[]), e os “labels” que os dados serão inseridos. Transformando tudo em uma lista.

Agora entendi. Então eu sempre terei que ter labels pra receber essas informações?
No caso podem ser labels vazias também, certo?

Nesse exemplo sim!

N labels para N campos.

Tanto faz, vazia ou não, o cursor vai atribuir o texto da label com o dado do cursor.

Boa tarde,

Voltando ao exemplo do link http://escoladeandroid.blogspot.com.br/2012/04/android-carregando-listview-com-sqlite.html

Tenho um layout com uma caixa de textos e um botão que grava informações no banco. Ao clicar no botão de gravar, gostaria que também fosse adicionada ao listView dessa tela a informação gravada, em tempo real.

No evento eu chamo esse método, mas acontece aquele erro force close assim que eu clico no botão. O que estou fazendo de errado? Quando comento esse código e só chamo gravar, e não o listar, ele grava normalmente.

[code]public void listar(){
//executa consulta geral de todos os registros cadastrados no banco de dados
Cursor grupos = database.query(“agenda”, “Nome_Grupo”, null, null, null, null, null);

    if (contatos.getCount() > 0){
        //cria cursor que será exibido na tela, nele serão exibidos 
        //todos os contatos cadastrados
        dataSource = new SimpleCursorAdapter(this, R.layout.modelo, grupos, 
                campos, new int[] { R.id.tvNome});
         
        //relaciona o dataSource ao próprio listview
        listView.setAdapter(dataSource);[/code]

Os imports estão todos corretos, referenciei cada componente nas classes. Criei um novo layout com uma label que vai receber a informação do banco (modelo).Registrei esse layout no mainfest normalmente.

Será que eu terei que mexer na classe do layout modelo??

Você poderia postar os logs do erro? Se possível também o código completo da classe.

Abraços…

Não estou na máquina agora, mas vou postar os códigos:

Layout com caixa de texto e botão para gravar grupo
activity_grupos

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/grupos" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_addGroup" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Gravar" /> <ListView android:id="@+id/listView1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>

Layout onde vou carregar a lista que vem do banco

modelo_lista.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Resultado Lista" /> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Resultado Lista" /> </LinearLayout>

Arquivo de conexão/criação do banco de dados (só estou usando o método de gravar o grupo, nele, ainda vou mudar os outros métodos)

ContextoDados.java

[code]package com.example.agenda;

import android.content.ContentValues;  
import android.content.Context;  
import android.database.Cursor;  
import android.database.SQLException;  
import android.database.sqlite.SQLiteCursor;  
import android.database.sqlite.SQLiteCursorDriver;  
import android.database.sqlite.SQLiteDatabase;  
import android.database.sqlite.SQLiteOpenHelper;  
import android.database.sqlite.SQLiteQuery;  
import android.util.Log;  

import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class ContextoDados extends SQLiteOpenHelper {  
	
	 
	    

	private static final String campos[]={"Nome_Grupo","Cod_Grupo"};	

  
    // O nome do arquivo de base de dados no sistema de arquivos */  
  
    private static final String NOME_BD = "Agenda";  
  
    // A versão da base de dados que esta classe compreende. */  
  
    private static final int VERSAO_BD = 2;  
  
    private static final String LOG_TAG = "Agenda";  
  
    // Mantém rastreamento do contexto que nós podemos carregar SQL */  
  
    private final Context contexto;  
  
    public ContextoDados(Context context) {  
        super(context, NOME_BD, null, VERSAO_BD);  
        this.contexto = context;  
    }  
  
    @Override  
    public void onCreate(SQLiteDatabase db) {  
        String[] sql = contexto.getString(R.string.ContextoDados_onCreate)  
                .split("\n");  
        db.beginTransaction();  
  
        try {  
            // Cria a tabela e testa os dados  
            ExecutarComandosSQL(db, sql);  
            db.setTransactionSuccessful();  
        } catch (SQLException e) {  
            Log.e("Erro ao criar as tabelas e testar os dados",e.toString());  
        } finally {  
            db.endTransaction();  
        }  
    }  
  
    @Override  
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
        Log.w(LOG_TAG, "Atualizando a base de dados da versao " + oldVersion  
                + " para " + newVersion  
                + ", que destruirá todos os dados antigos");  
        String[] sql = contexto.getString(R.string.ContextoDados_onUpgrade)  
                .split("\n");  
        db.beginTransaction();  
  
        try {  
            ExecutarComandosSQL(db, sql);  
            db.setTransactionSuccessful();  
        } catch (SQLException e) {  
            Log.e("Erro ao atualizar as tabelas e testar os dados",  
                    e.toString());  
            throw e;  
        } finally {  
            db.endTransaction();  
        }  
  
        onCreate(db);  
    }  
  
    /** 
     * Executa todos os comandos SQL passados no vetor String[] 
     *  
     * @param db 
     *            A base de dados onde os comandos serão executados 
     * @param sql 
     *            Um vetor de comandos SQL a serem executados 
     */  
    private void ExecutarComandosSQL(SQLiteDatabase db, String[] sql) {  
        for (String s : sql)  
            if (s.trim().length() > 0)  
                db.execSQL(s);  
    }  
  
    public String ConsultaGrupo() {  
       String dados= "";  
      
        SQLiteDatabase bd = getReadableDatabase();  
      
        Cursor c = bd.query("Grupos",  
                new String[] {"Nome_Grupo"},null, null, null, null, null);  
  
      /*  if (c.getCount() > 0) {  
            c.moveToFirst();  
            dados = c.getString(2);  */
            
         /*   if (c.getCount()>0){
            	dataSource = new SimpleCursorAdapter(this,R.layout.modelo_lista, c,campos,new int[]{R.id.tv1});
            //	dataSource = new SimpleCursorAdapter(this,R.layout.modelo_lista,c,new String[] {"Nome_Grupo"},new int[]{R.id.tv1});
            	listView.setAdapter(dataSource);
              
        } else {  
            mensagem("Nome não cadastrado");  
        }  */
  
        return dados;  
    }  

      
    public long ExcluirContato(String nome) {  
        SQLiteDatabase db = getReadableDatabase();  
  
        try {  
            return db.delete("Contatos", "Nome='"+ nome + "'",null);  
        } finally {  
            db.close();  
        }  
    }  
      
    public long AtualizarContato(String nome, String telefone) {  
        SQLiteDatabase db = getReadableDatabase();  
  
        try {  
            ContentValues valores = new ContentValues();  
            valores.put("Telefone", telefone);  
              
            return db.update("Contatos", valores ,"Nome='" + nome + "'",null);  
        } finally {  
            db.close();  
        }  
    }  
      
    public long InserirGrupos(String nome) {  
        SQLiteDatabase db = getReadableDatabase();  
  
        try {  
            ContentValues initialValues = new ContentValues();  
            initialValues.put("Nome_Grupo", nome);  
            
          
            return db.insert("Grupos", null, initialValues);  
        } finally {  
            db.close();  
    }  
    }  
  
    public void mensagem(String msg) {  
        Toast t = Toast.makeText(this.contexto, msg, Toast.LENGTH_LONG);  
        t.show();  
    }  


}  

[/code]

Grupos.java

[code]package com.example.agenda;
import android.os.Bundle;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.widget.SimpleCursorAdapter;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class Grupos extends Activity implements OnClickListener{
private SQLiteDatabase db;
private CursorAdapter dataSource;
ContextoDados helper;

private static final String campos[]={“Nome_Grupo”,“Cod_Grupo”};

Button btnGroup;
EditText txtNome;

ListView listView;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_grupos);

listView = (ListView) findViewById(R.id.listView1);    
txtNome = (EditText) findViewById(R.id.grupos);
btnGroup    = (Button) findViewById(R.id.btn_addGroup);
btnGroup.setOnClickListener(this);

helper = new ContextoDados(this);

db = helper.getReadableDatabase();

}

public void onClick(View v){
//	CadastrarGrupo();
	listar();

	
}


public void CadastrarGrupo()    {  
   ContextoDados db = new ContextoDados(this);
   db.InserirGrupos(txtNome.getText().toString());
   db.mensagem("Dados gravados") ;  
	    
}

public void listar(){
Cursor grupos = db.query("Grupos",campos,null,null,null,null,null);
	if (grupos.getCount()>0){
	dataSource = new SimpleCursorAdapter(this,R.layout.modelo_lista,grupos,campos,new int[]{R.id.tv1,R.id.tv2});
	
	listView.setAdapter(dataSource);
	
	}
}
	
public void limpaCampos(EditText txtnome){
	
	txtnome.setText("");
	
	
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_grupos, menu);
    return true;
}

}[/code]

Quando chamo o método listar, ao clicar no botão, executa um erro fechando a aplicação. Não sei se entendi errado a parte de consultas, mas pelo que entendi:

através do db.query eu realizo uma consulta no Banco de Dados passando como parâmetro o nome da tabela, campos e alguma outra cláusula opcional

Depois disso, instancio um dataSource, onde ele vai associar esses dados a um modelo de listview que foi definido no arquivo modelo_lista, ou seja, os dados serão carregados no lugar das labels dessa tela.

depois seto a listView com os valores do banco.

Há algo errado na implementação? Não ocorre nenhum erro na hora de compilar, só executando mesmo.

No método CadastrarGrupo() tente utilizar outro nome para o objeto “db”, pois você já tem uma variável global com o mesmo nome, isso pode confuncir a JVM quando você chama os métodos dessa classe mais abaixo, ou seja, ela não sabe se tem que usar a variável local ou a global nas linhas 56 e 57.

Abraços…

Mas aí é que tá:

O método CadastrarGrupo, funciona perfeitamente, já o listar (que inclusive não tem instanciado o db) não está funcionando.

A questão está no listar mesmo.