Entendendo melhor SQLiteOpenHelper e utilização

Eu estou com algumas duvidas com relação à estrutura da utilização do SQLiteOpenHelper junto com o SQLitedatabase.
Li este tutorial e ainda não consegui entender muito bem a função dessa classe.
Pelo que vi deve-se extender a classe SQLiteOpenHelper e implementar onCreate e onUpgrade. Vamos supor que esta se chame DBHelper como vi no tutorial.
Depois, uma outra classe qualquer deve ter uma instancia de DBHelper e uma do SQLitedatabase. Suponhamos da mesma maneira que esta se chama DBAdapter.
É a partir daí que eu não entendo, porque o DBHelper é usado apenas uma vez, no construtor de DBAdapter. Mas em que momento e em que classe do app eu devo instanciar a classe DBAdapter? E o onCreate é chamado quando eu faço essa instanciação ou quando eu tento executar a primeira operação no banco?
O DBHelper é usado apenas no construtor mesmo? Ele não é usado em mais NADA?
E por ultimo, onde eu devo usar metodos como o getWritableDatabase() e close() e quais trechos de codigo eu devo circundar com try catch?

Eu sei que é muita duvida mas por favor me ajudem porque eu já estou tentado entender isso corretamente ha dias.

O SQLiteOpenHelper também gerencia versões do banco de dados.

Caso voce mude algo na estrutura de alguma tabela, você indica nele que o DB_VERSION mudou, e o método onUpgrade(int oldVersion, int newVersion) vai ser invocado com os novos valores para voce ter a possibilidade de dar um ALTER_TABLE na tabela. Normalmente você cai nesse caso na atualização de aplicativos.

Continuo na mesma. Você é um grande filósofo, amigão.

Foi mal heheh

É o seguinte, quando voce desenvolve o sistema e lança com certa estrutura no banco de dados, voce vai ter implementado o Helper como o seguinte:

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBSupport extends SQLiteOpenHelper {
	private static final String DB_NAME = "library.db";
	private static final int DB_VERSION = 1;

	public DBSupport(Context context) {
		super(context, DB_NAME, null, DB_VERSION);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(LibraryDAO.createLibraryStatement);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	}
}

Depois de lançado, imagine que voce precise em uma atualização adicionar um novo campo na tabela, você irá mudar o DB_VERSION e fazer as alterações de versoes antigas, como o seguinte:

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBSupport extends SQLiteOpenHelper {
	private static final String DB_NAME = "library.db";
	private static final int DB_VERSION = 2;

	public DBSupport(Context context) {
		super(context, DB_NAME, null, DB_VERSION);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(LibraryDAO.createLibraryStatement);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	    db.execSQL("ALTER TABLE LIBRARY ADD COLUMN createdAt TEXT");
	    db.execSQL("ALTER TABLE LIBRARY ADD COLUMN openedAt INTEGER");
	    db.execSQL("ALTER TABLE LIBRARY ADD COLUMN lastPage TEXT");
	    db.execSQL("ALTER TABLE LIBRARY ADD COLUMN " + LibraryDAO.LibraryMetadata.CONTENT_ID.fieldAndType());
	    db.execSQL("update LIBRARY set openedAt = 0");

	    if(oldVersion == 1)
                 return;
	}
}

Você não entendeu. Não estou com duvidas na criação, gerenciamento, exclusao, alteração e etc do banco de dados. Eu não sei é como vai funcionar o query, o insert, e operações basicas. Não consegui assimilar a relação entre o SQLiteOpenHelper e o SQLitedatabase nas operações cotidianas.
O Ricardo Lecheta no livro dele explicou primeiro como se faz para importar um sqlite para o emulador e só depois em cima disso explicou como criar o banco atraves da API ao inves de fazer a importação. Ou seja, ele explicou como alterar um aplicativo que usava importação para agora criar via API, mas não explicou como criar da API desde o começo.
Le com atenção a minha primeira pergunta que vc entende.

Olha só a diferença do primeiro tutorial que eu postei la em cima e este. Cada um faz de um jeito, o de todo mundo funciona. O meu não.

Olá
A sequência é a seguinte:

DBHelper dbHelper = new DBHelper(contexto);
SQLiteDatabase db = dbHelper.getWritableDatabase(); // ou Readable -> aqui vai criar do db na primeira vez
// usa o db.insert, db.update, db.delete, db.query…
// para fechar
dbHelper.close();

Normalmente você coloca isso numa classe DBAdapter

Duplicado

A classe DBHelper não pode extender SQLiteOpenHelper e ter em si uma instancia de SQLitedatabase para fazer as operações? E eu ainda tenho as dúvidas que eu escrevi na primeira postagem.

DBHelper extends a SQLiteOpenHelper.
É apenas uma classe utilitária para facilitar a manutenção do SQLite.
Pode usar direto do SQLIte.

A diferença entre os dois tutoriais é que o primeiro separou em duas classes e o segundo deixou tudo numa mesma classe.

PS: Note que nenhum dos dois tutoriais estão completos e perfeitos. Não vi se tem o projeto completo para dowload.

incrivel como a galera consegue responder, responder, responder e responder, e não responder o que eu perguntei.

Quem sabe se você tentar perguntar de outra maneira, porque quem não está entendendo agora sou eu.
Qual é a dúvida?
A classe SQLiteOpenHelper você estende e implementa alguns métodos.
Nela tem o método que te retorna uma instancia do db
Você usa a instancia retornada para realizar leitura/inserts/updates/queries/etc no db
Pergunto de novo onde está a dúvida?

public static final String COLUNA_MARCA = "marca"; public static final String COLUNA_MODELO = "modelo"; public static final String COLUNA_ANO = "ano"; public static final String COLUNA_PLACA = "placa";

public void onCreate(SQLiteDatabase db) { String SQL_CREATE = "CREATE TABLE " + TABLE + "( " + COLUNA_MARCA + " TEXT NOT NULL ," + COLUNA_MODELO + " TEXT NOT NULL ," + COLUNA_ANO + "TEXT NOT NULL, " + COLUNA_PLACA + " TEXT PRIMARY KEY)"; db.execSQL(SQL_CREATE); Log.i(tag, "BANCO CRIADO"); }

public void salvar(Carro carro) { SQLiteDatabase db = this.getWritableDatabase(); db.insert(TABLE, null, carro.getContentValues()); Toast.makeText(context, carro.modelo + " adicionado.", Toast.LENGTH_SHORT).show(); db.close(); }

public ContentValues getContentValues() { ContentValues cv = new ContentValues(); cv.put(Database.COLUNA_MARCA, this.marca); cv.put(Database.COLUNA_MODELO, this.modelo); cv.put(Database.COLUNA_ANO, this.ano); cv.put(Database.COLUNA_PLACA, this.placa); return cv; }

E o problema da vez é…

[color=red]06-08 10:43:18.985: E/SQLiteDatabase(543): Error inserting placa=PLACA ano=2000 marca=Marca modelo=Modelo
06-08 10:43:18.985: E/SQLiteDatabase(543): android.database.sqlite.SQLiteException: table CARROS has no column named ano: , while compiling: INSERT INTO CARROS(placa,ano,marca,modelo) VALUES (?,?,?,?)
[/color]

[color=#444444]Existe explicação? [/color]

Pode ter criado a tabela sem essa coluna?
Incrementa um na versão do db e tenta recriar usando o onUpgrade para deletar e recriar a tabela

ps: onUpgrade

Faltou um espaço na linha seguinte, "TEXT… deve ser " TEXT…

Já implementei um botão na activity que faz isso. Se eu acabo de de recriar o banco e clico em salvar denovo, ele da o mesmo erro.

[quote=A H Gusukuma]Faltou um espaço na linha seguinte, "TEXT… deve ser " TEXT…

A madrugada inteira por causa de UM espaço…

Te amo cara…

Em breve eu posto os próximos erros, o banco de dados não vai me deixar ser feliz tão cedo, mas um dia eu venço.

Uma duvida rápida sobre o close().
Qual a hora certa que eu devo usa-lo? Ele deve ser usado dentro do meu helper (SQLiteDatabase.close()) dentro de cada operação tipo:

public void salvar(Carro carro) { SQLiteDatabase db = this.getWritableDatabase(); db.insert(TABLE, null, carro.getContentValues()); Toast.makeText(context, carro.modelo + " adicionado.", Toast.LENGTH_SHORT).show(); db.close(); }

Ou deve ser usado na Activity sobre a instancia desssa classe? (SQLiteOpenHelper.close())

DBHelper helper = new DBHelper(context); ... helper.close();

Atualizando: é impressão minha ou eu não consigo mais usar o cursor se der close()?