Como usar banco de dados em uma aplicação android


Um dos grandes diferenciais da plataforma android é a grande quantidade de módulos e APIsSQLiteque as aplicações tem à  disposição para usar. Eles dão muito poder ao desenvolvedores, permitindo que estes façam coisas que eram impossíveis em outras plataformas móveis.

Um dos mais importantes módulos é o SQLite. Sim, amigos, já temos um SGDB (Sistema gerenciador de bancos de dados) instalado e pronto para usar! E é exatamente o que faremos no artigo de hoje.

No artigo anterior vimos como criar um Content Provider. Usaremos este provider para acessar o banco de dados.

Para fazer isso, precisamos implementar os métodos da classe ContentProvider que vimos no artigo passado (query(), delete(), update(), etc…)  para prover ao usuário os métodos para criar, atualizar, deletar e recuperar os dados. Além disso, usaremos a classe SQLiteOpenHelper para gerenciar a conexão com o banco de dados.

A classe SQLiteOpenHelper

A classe SQLiteOpenHelper, como dito anteriormente, será usada para gerenciar o banco de dados. Para usá-la, é preciso criar uma subclasse implementando os métodos abaixo:

  • onCreate() – Este método é chamado quando a conexão com o banco de dados for aberta pela primeira vez. É aqui que criaremos o banco de dados, com o comando sql CREATE.
  • onUpdate() – Este método é chamado quando a versão do banco de dados muda. Por exemplo, digamos que você criou uma nova versão de seu aplicativo que usa uma tabela a mais no banco de dados. Quando esta nova versão for instalada (em um telefone que já possuir a primeira versão) este método será chamado, então você poderá criar apenas a nova  tabela, mantendo os dados do usuário.

O código

O código do QuickNotesProvider fica assim, acessando o banco de dados. A seguir, eu explico algumas coisas que podem gerar dúvidas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package br.com.felipesilveira.quicknotes;
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.Context;
import android.content.UriMatcher;
import android.net.Uri;
import android.provider.BaseColumns;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
public class QuickNotesProvider extends ContentProvider {
    // Authority do nosso provider, a ser usado nas Uris.
    public static final String AUTHORITY =
        "br.com.felipesilveira.quicknotes.quicknotesprovider";
    
    // Nome do arquivo que irá conter o banco de dados.
    private static  final String DATABASE_NAME = "quicknotes.db";
    
    // Versao do banco de dados.
    // Este valor é importante pois é usado em futuros updates do DB.
    private static  final int  DATABASE_VERSION = 1;
    
    // Nome da tabela que irá conter as anotações.
    private static final  String NOTES_TABLE = "notes";
    // 'Id' da Uri referente às notas do usuário.
    private  static final int NOTES = 1;
    // Tag usada para imprimir os logs.
    public static final String TAG = "QuickNotesProvider";
    
    // Instância da classe utilitária
    private DBHelper mHelper;
    
    // Uri matcher - usado para extrair informações das Uris
    private static final UriMatcher mMatcher;
    private static HashMap<String, String> mProjection;
    
    static {
        mProjection = new HashMap<String, String>();
        mProjection.put(Notes.NOTE_ID, Notes.NOTE_ID);
        mProjection.put(Notes.TEXT, Notes.TEXT);   
    }
    
    static {
        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        mMatcher.addURI(AUTHORITY, NOTES_TABLE, NOTES);
    }
    
    
    /////////////////////////////////////////////////////////////////
    //           Métodos overrided de ContentProvider              //
    /////////////////////////////////////////////////////////////////
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase db = mHelper.getWritableDatabase();
        int count;
        switch (mMatcher.match(uri)) {
            case NOTES:
                count = db.delete(NOTES_TABLE, selection, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException(
                  "URI desconhecida " + uri);
        }
     
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }
    @Override
    public String getType(Uri uri) {
            switch (mMatcher.match(uri)) {
                case NOTES:
                    return Notes.CONTENT_TYPE;
                default:
                    throw new IllegalArgumentException(
                        "URI desconhecida " + uri);
            }
    }
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        switch (mMatcher.match(uri)) {
            case NOTES:
                SQLiteDatabase db = mHelper.getWritableDatabase();
                long rowId = db.insert(NOTES_TABLE, Notes.TEXT, values);
                if (rowId > 0) {
                    Uri noteUri = ContentUris.withAppendedId(
                                 Notes.CONTENT_URI, rowId);
                    getContext().getContentResolver().notifyChange(
                                 noteUri, null);
                    return noteUri;
                }
            default:
                throw new IllegalArgumentException(
                        "URI desconhecida " + uri);
        }
    }
    @Override
    public boolean onCreate() {
        mHelper = new DBHelper(getContext());;
        return true;
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
            // Aqui usaremos o SQLiteQueryBuilder para construir
            // a query que será feito ao DB, retornando um cursor
            // que enviaremos à aplicação.
            SQLiteQueryBuilder builder = new  SQLiteQueryBuilder();
            SQLiteDatabase database = mHelper.getReadableDatabase();
            Cursor cursor;
            switch (mMatcher.match(uri)) {
                case NOTES:
                    // O Builer receberá dois parametros: a tabela
                    // onde será feita a busca, e uma projection -
                    // que nada mais é que uma HashMap com os campos
                    // que queremos recuperar do banco de dados.
                    builder.setTables(NOTES_TABLE);
                    builder.setProjectionMap(mProjection);
                    break;
     
                default:
                    throw new IllegalArgumentException(
                          "URI desconhecida " + uri);
            }
 
            cursor = builder.query(database, projection, selection,
             selectionArgs, null, null, sortOrder);
            cursor.setNotificationUri(getContext().getContentResolver(), uri);
            return cursor;
    }
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
            SQLiteDatabase db = mHelper.getWritableDatabase();
            int count;
            switch (mMatcher.match(uri)) {
                case NOTES:
                    count = db.update(NOTES_TABLE, values,
                                                     selection, selectionArgs);
                    break;  
                default:
                    throw new IllegalArgumentException(
                            "URI desconhecida " + uri);
            }
     
            getContext().getContentResolver().notifyChange(uri, null);
            return count;
    }
    
    /////////////////////////////////////////////////////////////////
    //                Inner Classes utilitárias                    //
    /////////////////////////////////////////////////////////////////
    public static final class  Notes implements  BaseColumns {
        public static final Uri CONTENT_URI = Uri.parse("content://"
                    + QuickNotesProvider.AUTHORITY + "/notes");
     
        public static final String CONTENT_TYPE =
                "vnd.android.cursor.dir/" + QuickNotesProvider.AUTHORITY;
     
        public static final String NOTE_ID = "_id";
     
        public static final String TEXT = "text";
    }
    
    private static class DBHelper extends SQLiteOpenHelper {
     
        DBHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
     
        /* O método onCreate é chamado quando o provider é executado pela
         * primeira vez, e usado para criar as tabelas no database
         */
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE " + NOTES_TABLE + " (" +
                    Notes.NOTE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
                    Notes.TEXT + " LONGTEXT" + ");");
        }
            
        /* O método onUpdate é invocado quando a versão do banco de dados
         * muda. Assim, é usado para fazer adequações para a aplicação
         * funcionar corretamente.
         */
        @Override
        public void onUpgrade(SQLiteDatabase db,
                                      int oldVersion, int newVersion) {
            // Como ainda estamos na primeira versão do DB,
            // não precisamos nos preocupar com o update agora.
        }
    }
}

Cursores

O primeiro conceito importante a se falar é o conceito dos Cursores. Como você deve percebido, este é o tipo de retorno do método query(), e não é por acaso: Os cursores são “apontadores de dados” do banco de dados – ou seja, uma interface que permite o acesso aos dados retornados pela query enviada pelo usuário.

notifyChanges()

Em todos os métodos em que alteramos o banco de dados (inserimos, deletamos ou modificamos dados) é importante chamar o método modifyChanges(). Isso fará com que as aplicações que estejam utilizando este conjunto de dados sejam notificadas, permitindo a estas atualizar também os dados mostrados ao usuário.

No próximo post iremos usar o QuickNotesProvider na nossa aplicação.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s