Comecei um projeto pessoal, e para facilitar a comunicação com o banco de dados sqlite, eu pesquisei um pouco sobre ContentProvider, e achei válido postar aqui um tutorial, sendo que com um ContentProvider, toda a parte de comunicação com o banco de dados fica bem mais simples.
ContentProvider serve para comunicar com o sqlite no android e retornar cursor com os registros sem a necessidade de montar um sql para todo comando, ele também é responsável por toda operação CRUD (create, read, update, delete) do aplicativo.
Bom para começar vamos definir uma tabela, criando uma classe para isso:
public class TutorialTable {
//Tabela do BD
public static final String TABLE_TUTORIAL = "tutorial";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_DESCRICAO = "descricao";
// SQL para criar a tabela
private static final String DATABASE_CREATE = "create table "
+ TABLE_TUTORIAL
+ "("
+ COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_DESCRICAO + " text not null "
+ ");";
public static void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE);
}
public static void onUpgrade(SQLiteDatabase database, int oldVersion,
int newVersion) {
database.execSQL("DROP TABLE IF EXISTS " + TABLE_TUTORIAL);
onCreate(database);
}
}
A classe da tabela é bem simples, primeiro definimos uma variável om o nome da tabela e das colunas (para acessar mais tarde), depois definimos o SQL para criar a tabela, e o upgrade (para quando mudarmos alguma coluna, aqui para facilitar ele da DROP e depois CREATE novamente, mas se não quiser ter perda de dados, poderíamos apenas usar ALTER TABLE para adicionar e remover colunas, porém teríamos que controlar as versões, como aqui é apenas para testes vou utilizar a maneira mais fácil.
Depois criaremos uma classe que será o DatabaseHelper, que fará a criação do BD e a atualização do mesmo.
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "tutorial.db";
private static final int DATABASE_VERSION = 1;
public IGDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Método chamado ao criar o BD
@Override
public void onCreate(SQLiteDatabase database) {
TutorialTable.onCreate(database);
}
// Método chamado na atualização do BD, se você mudar o DATABASE_VERSION ele irá chamar esse método
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion,
int newVersion) {
TutorialTable.onUpgrade(database, oldVersion, newVersion);
}
}
Pronto, temos nossa tabela e nosso BD funcionando, lembrando que para cada tabela é bom criar uma classe diferente, e lembrar de adicionar o onCreate e onUpgrade no databasehelper.
Agora só falta a classe que será responsável pela comunicação com o BD, que será nosso ContentProvider.
public class CustomContentProvider extends ContentProvider {
private DatabaseHelper database;
private static final String AUTHORITY = "com.caioketo.tutorial.contentprovider";
// ------- Definimos URIs uma para cada tabela
private static final String PATH_TUTORIAL = "tutorial";
public static final Uri CONTENT_URI_TUTORIAL = Uri.parse("content://" + AUTHORITY
+ "/" + PATH_TUTORIAL);
// ------- Configurando o UriMatcher
private static final int TUTORIAL = 10;
private static final int TUTORIAL_ID = 20;
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, PATH_PERGUNTAS, TUTORIAL);
sURIMatcher.addURI(AUTHORITY, PATH_PERGUNTAS + "/#", TUTORIAL_ID);
}
@Override
public boolean onCreate() {
return false;
}
//@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Vamos utilizar o queryBuilder em vez do método query()
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case TUTORIAL_ID:
// Adicionamos a coluna ID
queryBuilder.appendWhere(TutorialTable.COLUMN_ID + "="
+ uri.getLastPathSegment());
//$FALL-THROUGH$
case TUTORIAL:
queryBuilder.setTables(TutorialTable.TABLE_PERGUNTA);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = database.getWritableDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, null, null, sortOrder);
// Notificamos caso exista algum Listener
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
public String getPATH(int pathID) {
switch (pathID) {
case TUTORIAL:
return PATH_PERGUNTAS;
default:
return "";
}
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = database.getWritableDatabase();
int rowsDeleted = 0;
long id = 0;
switch (uriType) {
case TUTORIAL:
id = sqlDB.insert(TutorialTable.TABLE_TUTORIAL, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(getPATH(uriType) + "/" + id);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = database.getWritableDatabase();
int rowsDeleted = 0;
switch (uriType) {
case TUTORIAL:
rowsDeleted = sqlDB.delete(TutorialTable.TABLE_TUTORIAL, selection,
selectionArgs);
break;
case TUTORIAL_ID:
String id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = sqlDB.delete(TutorialTable.TABLE_TUTORIAL,
TutorialTable.COLUMN_ID + "=" + id,
null);
} else {
rowsDeleted = sqlDB.delete(TutorialTable.TABLE_TUTORIAL,
TutorialTable.COLUMN_ID + "=" + id
+ " and " + selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = database.getWritableDatabase();
int rowsUpdated = 0;
switch (uriType) {
case TUTORIAL:
rowsUpdated = sqlDB.update(TutorialTable.TABLE_TUTORIAL,
values,
selection,
selectionArgs);
break;
case TUTORIAL_ID:
String id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = sqlDB.update(TutorialTable.TABLE_TUTORIAL,
values,
TutorialTable.COLUMN_ID + "=" + id,
null);
} else {
rowsUpdated = sqlDB.update(TutorialTable.TABLE_TUTORIAL,
values,
TutorialTable.COLUMN_ID + "=" + id
+ " and "
+ selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
private void checkColumns(String[] projection) {
String[] available = { TutorialTable.COLUMN_DESCRICAO, PerguntasTable.COLUMN_ID };
if (projection != null) {
HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
// check if all columns which are requested are available
if (!availableColumns.containsAll(requestedColumns)) {
throw new IllegalArgumentException("Unknown columns in projection");
}
}
}
}
Primeiro definimos a AUTHORITY que será o path do app, para encontrar o BD, depois definimos Uris para cada tabela, e então configuramos o UriMatcher para pegar pelo ID em vez da Uri, para melhorar a velocidade. E então criamos nosso ContentProvider, os métodos são básicos como podem ver:
query(): Seria como um select, retorna um Cursor com os registros encontrados;
getPATH(): Para retornar o PATH pelo ID;
insert(): Como o nome mesmo já diz, insere registros na tabela;
delete(): Deleta registros;
update(): Atualiza os registros;
checkColumns(): esse a gente cria para verificar se a coluna existe antes de executar qualquer comando SQL, caso mude as colunas ele não vai dar erro de SQL, pois trataremos antes.
IMPORTANTE:
Após a criação do ContentProvider temos que declará-lo no AndroidManifest.XML
<provider
android:authorities="com.caioketo.tutorial.CustomContentProvider"
android:name=".dao.CustomContentProvider" >
</provider>
E agora sim estamos prontos para trabalhar com o BD, sempre iremos usar o ContentProvider para todas as operações, e podemos até criar um método no ContentProvider para executar um comando SQL (se nescessário) para apenas essa classe se comunicar diretamente com o BD, assim encapsulamos a comunicação.E aqui finalizo mais um post, qualquer dúvida, sugestão, erro, etc, favor deixar comentários, e até a próxima.
Nenhum comentário:
Postar um comentário