Flutter - Acessando o SQLite
Hoje veremos como acessaro SQLite no Flutter usando o plugin sqflite. |
|
O Flutter é um SDK de aplicativo móvel do Google que ajuda a criar aplicativos móveis modernos para iOS e Android usando uma única (quase) base de código.
Se você não conhece o Flutter veja o meu artigo : Flutter - Primeiros contatos e impressões
Acessando o SQLite
Podemos acessar o banco de dados SQLite no Flutter usando o plugin sqlflite cuja documentação pode ser acessada neste link: sqflite
Este plugin oferce os seguintes recursos:
Existe um procedimento padrão básico que geralmente consiste em:
Criando o projeto Flutter e definindo as dependências
No Visual Studio Code tecle CTRL+ SHIFT+P para abrir a paleta de comandos e a seguir selecione a opção : Fluter:New Project
A seguir informe o nome do projeto : flutter_database1
e tecle ENTER
Na janela de
diálogo a seguir selecione a pasta onde o projeto vai ser salvo e clique em :
Select a folder to create the project in
O Flutter vai criar um projeto padrão onde todo o código da aplicação vai estar no arquivo main.dart dentro da pasta lib do projeto.
Vamos iniciar definindo no arquivo pubspec.yaml as dependências ao sqflite ao path_provider :
A dependência path_provider é um plug-in Flutter para encontrar locais comumente usados no sistema de arquivos.
Criando a classe de acesso aos dados
Vamos agora criar a classe de acesso aos dados, ou seja, a classe database helper onde vamos definir os métodos para acessar o banco de dados.
Para simplificar vamos usar esta classe para também criar o banco de dados e a tabela que iremos acessar.
Vamos criar o banco de dados ExemploDB.db e uma tabela chamada contato com 3 campos : id, nome e idade
No projeto criado, dentro da pasta lib, crie o arquivo database_helper.dart e a seguir inclua o código abaixo neste artigo:
import 'dart:io';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
class DatabaseHelper {
static final _databaseName = "ExemploDB.db";
static final _databaseVersion = 1;
static final table = 'contato';
static final columnId = '_id';
static final columnNome = 'nome';
static final columnIdade = 'idade';
// torna esta classe singleton
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
// tem somente uma referência ao banco de dados
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
// instancia o db na primeira vez que for acessado
_database = await _initDatabase();
return _database;
}
// abre o banco de dados e o cria se ele não existir
_initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(path,
version: _databaseVersion,
onCreate: _onCreate);
}
// Código SQL para criar o banco de dados e a tabela
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY,
$columnNome TEXT NOT NULL,
$columnIdade INTEGER NOT NULL
)
''');
}
// métodos Helper
//----------------------------------------------------
// Insere uma linha no banco de dados onde cada chave
// no Map é um nome de coluna e o valor é o valor da coluna.
// O valor de retorno é o id da linha inserida.
Future<int> insert(Map<String, dynamic> row) async {
Database db = await instance.database;
return await db.insert(table, row);
}
// Todas as linhas são retornadas como uma lista de mapas, onde cada mapa é
// uma lista de valores-chave de colunas.
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database db = await instance.database;
return await db.query(table);
}
// Todos os métodos : inserir, consultar, atualizar e excluir,
// também podem ser feitos usando comandos SQL brutos.
// Esse método usa uma consulta bruta para fornecer a contagem de linhas.
Future<int> queryRowCount() async {
Database db = await instance.database;
return Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM $table'));
}
// Assumimos aqui que a coluna id no mapa está definida. Os outros
// valores das colunas serão usados para atualizar a linha.
Future<int> update(Map<String, dynamic> row) async {
Database db = await instance.database;
int id = row[columnId];
return await db.update(table, row, where: '$columnId = ?', whereArgs: [id]);
}
// Exclui a linha especificada pelo id. O número de linhas afetadas é
// retornada. Isso deve ser igual a 1, contanto que a linha exista.
Future<int> delete(int id) async {
Database db = await instance.database;
return await db.delete(table, where: '$columnId = ?', whereArgs: [id]);
}
}
|
O código acima esta na linguagem Dart e se você nunca viu um código Dart pode estranhar a sintaxe.
Por exemplo, o que significa Future ?
Um código Dart é executado em uma única thread. Se o código for bloqueado por estar executando uma operação muito longa ou estiver esperando por uma operação de arquivo, o programa inteiro vai 'congelar'.
As operações assíncronas permitem que o seu programa conclua outro trabalho enquanto aguarda a conclusão de uma operação. O Dart usa objetos Future (futures) para representar os resultados de operações assíncronas. Para trabalhar com futures, você pode usar o async e o await ou a API Future.
Um future é um objeto Future<T>, que representa uma operação assíncrona que produz um resultado do tipo T. Se o resultado não for um valor utilizável, o tipo do future será Future<void>. Quando uma função que retorna um future é invocada, duas coisas acontecem:
Ao escrever código que depende de um future, você tem duas opções:
O código acima
usa Future e Future<T>. A classe
Future<T> é um
objeto que representa um cálculo atrasado.
Future é usado para representar um valor potencial, ou um erro, que estará
disponível em algum momento no futuro. Receptores de um Futuro podem registrar
callback (retornos de chamada) que manipulam o valor ou o erro assim que
estiverem disponíveis.
Outro recurso usado é o Map.
O recurso Map no Dart é um objeto que associa chaves ao valor. Nos Maps DART, existe uma interface projetada para manipular uma coleção de chaves que apontam para um valor.
Assim, o objeto Map é um par chave/valor simples. As chaves e valores em um mapa podem ser de qualquer tipo, e, como um Map é uma coleção dinâmica, Maps podem crescer e diminuir em tempo de execução.
Podemos declarar um Map de duas maneiras:
Criando a interface UI
Vamos agora definir uma interface bem simples no arquivo main.dart.
Como esse é nosso primeiro contato com o Sqlite não vou criar uma interface onde o usuário vai poder informar os valores.
Para simplificar vamos criar apenas 4 botões usando o widget RaisedButton empilhados em um widget Column.
Em cada button definimos o callback onPressed que vão chamar os métodos para realizar as operações CRUD.
Abra o arquivo main.dart e substitua o código pelo código abaixo:
import 'package:flutter/material.dart';
import 'package:flutter_database1/database_helper.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SQFlite Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
// referencia nossa classe single para gerenciar o banco de dados
final dbHelper = DatabaseHelper.instance;
// layout da homepage @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Exemplo de CRUD básico'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ RaisedButton( child: Text('Inserir dados', style: TextStyle(fontSize: 20),), onPressed: () {_inserir();}, ), RaisedButton( child: Text('Consultar dados', style: TextStyle(fontSize: 20),), onPressed: () {_consultar();}, ), RaisedButton( child: Text('Atualizar dados', style: TextStyle(fontSize: 20),), onPressed: () {_atualizar();}, ), RaisedButton( child: Text('Deletar dados', style: TextStyle(fontSize: 20),), onPressed: () {_deletar();}, ), ], ), ), ); } // métodos dos Buttons void _inserir() async { // linha para incluir Map<String, dynamic> row = { DatabaseHelper.columnNome : 'Macoratti', DatabaseHelper.columnIdade : 53 }; final id = await dbHelper.insert(row); print('linha inserida id: $id'); } void _consultar() async {
final todasLinhas = await dbHelper.queryAllRows();
print('Consulta todas as linhas:');
todasLinhas.forEach((row) => print(row));
}
void _atualizar() async {
// linha para atualizar
Map<String, dynamic> row = {
DatabaseHelper.columnId : 1,
DatabaseHelper.columnNome : 'Maria',
DatabaseHelper.columnIdade : 32
};
final linhasAfetadas = await dbHelper.update(row);
print('atualizadas $linhasAfetadas linha(s)');
}
void _deletar() async {
// Assumindo que o numero de linhas é o id para a última linha
final id = await dbHelper.queryRowCount();
final linhaDeletada = await dbHelper.delete(id);
print('Deletada(s) $linhaDeletada linha(s): linha $id');
}
}
|
Executando o projeto usando o emulador do Genymotion temos o resultado abaixo:
Vamos primeiro incluir um registro : Macoratti,53 ,e, a seguir vamos consultar,
depois vamos atualizar os dados para Maria,32, e consultar novamente. Para
concluir vamos deletar.
Após realizar as operações consultando a console vemos o resultado exibido conforme abaixo:
Pegue os arquivos do projeto aqui : Arquivos_Projeto_1.zip
"Não sejais
vagarosos no cuidado; sede fervorosos no espírito, servindo ao Senhor;
Alegrai-vos na esperança, sede pacientes na tribulação, perseverai na oração;"
Romanos 12:11,12
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
Flutter - Apresentando o widget MaterialApp - Macoratti
Flutter - Apresentando Flutter Studio - Macoratti
Flutter - Lista Básica - Macoratti
Flutter - Apresentando Widgets - Macoratti
Flutter - Obtendo dados da Web - Macoratti