Tutorial de Flutter SQFLite y ejemplos CRUD
Tutorial y ejemplos de Flutter SQFlite.
Cómo trabajar con bases de datos SQLite en Flutter.
¿Qué es Flutter?
*Flutter es el SDK de aplicaciones móviles de Google para crear interfaces nativas de alta calidad en iOS y Android en un tiempo récord.
Flutter funciona con código existente, es utilizado por desarrolladores y organizaciones de todo el mundo, y es gratuito y de código abierto.
Estas son las tres características principales de Flutter:
1. Desarrollo rápido
Flutter puede dar vida a tu aplicación en milisegundos mediante la recarga en caliente.
También puede emplear un rico conjunto de widgets totalmente personalizables para construir interfaces nativas en minutos.
2. Interfaz de usuario expresiva y flexible
Flutter le permite enviar rápidamente características con un enfoque en las experiencias nativas de los usuarios finales.
La arquitectura en capas permite una personalización completa, lo que resulta en una renderización increíblemente rápida y en diseños expresivos y flexibles.
3. Rendimiento nativo
Los widgets de Flutter incorporan todas las diferencias críticas de la plataforma, como el desplazamiento, la navegación, los iconos y las fuentes, para ofrecer un rendimiento nativo completo tanto en iOS como en Android.
¿Qué es SQFlite?
SQflite es un plugin para Flutter. Nos permite almacenar, recuperar y manipular nuestras bases de datos SQLite a través del código de flutter. SQflite es compatible con las plataformas Android e iOS.
Estas son algunas de las características de SQFlite:
- SQFlite contempla tanto las transacciones de la base de datos como los lotes.
- SQlite ha incorporado la gestión automática de versiones.
- SQFlite proporciona métodos fáciles de usar para insertar, consultar, actualizar así como eliminar datos de la base de datos.
- Estas operaciones CRUD se realizan en el hilo de fondo tanto en iOS como en Android. Esto libera a la UI para que siga respondiendo.
Cómo instalar SQFlite
La instalación de SQFlite es tan sencilla como la de cualquier otro paquete de Flutter. Está alojado en Dart Package Repository y se puede añadir como dependencia.
Para ello:
1. Ve a tu archivo pubspec.yaml:
Y añádelo como dependencia:
dependencies:
sqflite: ^0.12.1
Puedes consultar la última versión aquí.
2. Descárgalo
Android Studio te proporcionará un botón package get que lo recuperará y lo añadirá a tu proyecto siempre que estés conectado.
Si estás usando el código de Visual Studio, hacer un cambio en el archivo pubspec.yaml hará que el comando flutter packages get sea invocado automáticamente.
De lo contrario, si usted no está utilizando el IDE de arriba, entonces usted puede instalar desde la línea de comandos
$ flutter packages get
3. Importar a tu proyecto
Ve a tu código dart donde quieres usarlo e impórtalo al principio de tu archivo.
import 'package:sqflite/sqflite.dart';
Quick Flutter SQFLite Database HowTo Snippets
1. Cómo obtener la ruta de la base de datos
// Check if we have an existing copy first
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, "demo_asset_example.db");
2. Cómo abrir una base de datos
// try opening (will work if it exists)
Database db;
try {
db = await openDatabase(path, readOnly: true);
} catch (e) {
print("Error $e");
}
Puedes poner una clase de ayuda:
class Helper {
final String path;
Helper(this.path);
Database _db;
final _lock = Lock();
Future<Database> getDb() async {
if (_db == null) {
await _lock.synchronized(() async {
// Check again once entering the synchronized block
if (_db == null) {
_db = await openDatabase(path);
}
});
}
return _db;
}
O bien:
Future<Database> get db async {
if (_db != null) return _db;
_db = await initDb();
return _db;
}
mediante el cual initDb() es un método personalizado para obtenernos la ruta y abrirla como:
initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "test.db");
var theDb = await openDatabase(path, version: 1, onCreate: _onCreate);
return theDb;
}
3. Cómo crear una tabla de base de datos
Vamos a ver cómo podemos crear una tabla de base de datos en flutter con S
var db = await openDatabase(path);
await db.execute("CREATE TABLE IF NOT EXISTS Test(id INTEGER PRIMARY KEY)");
o:
void _onCreate(Database db, int version) async {
// When creating the db, create the table
await db.execute(
"CREATE TABLE Employee(id INTEGER PRIMARY KEY, firstname TEXT, lastname TEXT, mobileno TEXT,emailId TEXT )");
print("Created tables");
}
La db es el objeto Database. Invocamos su método execute() y le pasamos nuestra sentencia sql en bruto para que nos cree la tabla.
4. Cómo insertar en una tabla de la base de datos
await db.insert("Test", {"id": 1});
o:
Future<int> insertTodo(Todo todo) async {
Database db = await this.db;
var result = await db.insert(tblTodo, todo.toMap());
return result;
}
o digamos que quiero insertar una Persona con sus propiedades en la Base de Datos, y luego devolver la persona insertada:
Future insertPerson(Person person) async {
person.id = await _db.insert("people", person.toMap());
return person;
}
o
Future insertPerson(Person person) async {
person.id = await _db.insert("people", person.toMap());
return person;
}
5. Cómo consultar o seleccionar desde una tabla SQLite
await db.query("Test")
Digamos que quiero devolver un select y devolver una lista de Personas de la base de datos:
Future fetchEveryone() async {
List results = await _db.query("people", columns: Person.columns);
List people = new List();
results.forEach((map) {
people.add(Person.fromMap(map));
});
return people;
}
O digamos que queremos consultar una lista nuestra base de datos SQlite en flutter y poblar una Lista. También podemos usar una consulta cruda usando el método rawQuery. Se le pasa la sentencia SQL a ejecutar.
Future<List<Employee>> getEmployees() async {
var dbClient = await db;
List<Map> list = await dbClient.rawQuery('SELECT * FROM Employee');
List<Employee> employees = new List();
for (int i = 0; i < list.length; i++) {
employees.add(new Employee(list[i]["firstname"], list[i]["lastname"], list[i]["mobileno"], list[i]["emailid"]));
}
print(employees.length);
return employees;
}
U otro ejemplo:
Future<List> getTodos() async {
Database db = await this.db;
var result = await db.rawQuery("SELECT * FROM $tblTodo ORDER BY $colPriority ASC");
return result;
}
Digamos que quiero comprobar si un usuario está conectado:
Future<bool> isLoggedIn() async {
var dbClient = await db;
var res = await dbClient.query("User");
return res.length > 0 ? true : false;
}
7 . Cómo contar el número de elementos en SQLite
Future<int> getCount() async {
Database db = await this.db;
var result = Sqflite.firstIntValue(
await db.rawQuery("SELECT COUNT (*) FROM $tblTodo")
);
return result;
}
7. Cómo actualizar datos en la base de datos SQLite usando SQFLite
Future<int> updateTodo(Todo todo) async {
var db = await this.db;
var result = await db.update(tblTodo, todo.toMap(),
where: "$colId = ?", whereArgs: [todo.id]);
return result;
}
7. Cómo eliminar datos de la base de datos SQLite usando SQFLite
Future<int> deleteTodo(int id) async {
int result;
var db = await this.db;
result = await db.rawDelete('DELETE FROM $tblTodo WHERE $colId = $id');
return result;
}
O:
Future<int> deleteUsers() async {
var dbClient = await db;
int res = await dbClient.delete("User");
return res;
}
6. Cómo cerrar la base de datos
await db.close();
O:
Future close() async {
await _db.close();
}
Ejemplos completos
Veamos ahora algunos ejemplos completos con Flutter SQFlite.
(a). Flutter SQFLite - INSERT,SELECT,SHOW
Este es un sencillo tutorial de ejemplo de Dart Flutter que demuestra cómo realizar CRUD básico: Insertar, Seleccionar y Mostrar datos en una aplicación Flutter. Utilizaremos el plugin SQFLite de SQLite. Esto se debe a que nuestra base de datos es la SQLite
Proyecto de ejemplo completo
Aquí está el código fuente completo.
(a). pubspec.yaml
Nuestras dependencias:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
path_provider: '>=0.3.0'
sqflite: any
dev_dependencies:
flutter_test:
sdk: flutter
(b). employee.dart
Una clase dart para representar a un solo empleado con nombre, apellido, número de móvil y correo electrónico como propiedades. Estas propiedades se recibirán a través del constructor:
class Employee {
String firstName;
String lastName;
String mobileNo;
String emailId;
Employee(this.firstName, this.lastName, this.mobileNo, this.emailId);
Employee.fromMap(Map map) {
firstName = map[firstName];
lastName = map[lastName];
mobileNo = map[mobileNo];
emailId = map[emailId];
}
}
(c). dbhelper.dart
Una clase DBHelper para ayudar en la implementación de las operaciones de la base de datos:
import 'dart:async';
import 'dart:io' as io;
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_crud/model/employee.dart';
class DBHelper {
static Database _db;
Future<Database> get db async {
if (_db != null) return _db;
_db = await initDb();
return _db;
}
initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "test.db");
var theDb = await openDatabase(path, version: 1, onCreate: _onCreate);
return theDb;
}
void _onCreate(Database db, int version) async {
// When creating the db, create the table
await db.execute(
"CREATE TABLE Employee(id INTEGER PRIMARY KEY, firstname TEXT, lastname TEXT, mobileno TEXT,emailId TEXT )");
print("Created tables");
}
void saveEmployee(Employee employee) async {
var dbClient = await db;
await dbClient.transaction((txn) async {
return await txn.rawInsert(
'INSERT INTO Employee(firstname, lastname, mobileno, emailid ) VALUES(' +
''' +
employee.firstName +
''' +
',' +
''' +
employee.lastName +
''' +
',' +
''' +
employee.mobileNo +
''' +
',' +
''' +
employee.emailId +
''' +
')');
});
}
Future<List<Employee>> getEmployees() async {
var dbClient = await db;
List<Map> list = await dbClient.rawQuery('SELECT * FROM Employee');
List<Employee> employees = new List();
for (int i = 0; i < list.length; i++) {
employees.add(new Employee(list[i]["firstname"], list[i]["lastname"], list[i]["mobileno"], list[i]["emailid"]));
}
print(employees.length);
return employees;
}
}
(d). emloyeelist.dart
En este fichero se obtendrá una lista de empleados de forma asíncrona y se renderizará en un listview:
import 'package:flutter/material.dart';
import 'package:flutter_crud/model/employee.dart';
import 'dart:async';
import 'package:flutter_crud/database/dbhelper.dart';
Future<List<Employee>> fetchEmployeesFromDatabase() async {
var dbHelper = DBHelper();
Future<List<Employee>> employees = dbHelper.getEmployees();
return employees;
}
class MyEmployeeList extends StatefulWidget {
MyEmployeeListPageState createState() => new MyEmployeeListPageState();
}
class MyEmployeeListPageState extends State<MyEmployeeList> {
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Employee List'),
),
body: new Container(
padding: new EdgeInsets.all(16.0),
child: new FutureBuilder<List<Employee>>(
future: fetchEmployeesFromDatabase(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return new ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(snapshot.data[index].firstName,
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 18.0)),
new Text(snapshot.data[index].lastName,
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 14.0)),
new Divider()
]);
});
} else if (snapshot.hasError) {
return new Text("${snapshot.error}");
}
return new Container(alignment: AlignmentDirectional.center,child: new CircularProgressIndicator(),);
},
),
),
);
}
}
(e). main.dart
La clase main, donde definimos nuestro método main, el punto de entrada a nuestra aplicación dart:
import 'package:flutter/material.dart';
import 'package:flutter_crud/database/dbhelper.dart';
import 'package:flutter_crud/model/employee.dart';
import 'package:flutter_crud/employeelist.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
Widget build(BuildContext context) {
return new MaterialApp(
title: 'SQFLite DataBase Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Employee employee = new Employee("", "", "", "");
String firstname;
String lastname;
String emailId;
String mobileno;
final scaffoldKey = new GlobalKey<ScaffoldState>();
final formKey = new GlobalKey<FormState>();
Widget build(BuildContext context) {
return new Scaffold(
key: scaffoldKey,
appBar: new AppBar(
title: new Text('Saving Employee'),
actions: <Widget>[
new IconButton(
icon: const Icon(Icons.view_list),
tooltip: 'Next choice',
onPressed: () {
navigateToEmployeeList();
},
),
]
),
body: new Padding(
padding: const EdgeInsets.all(16.0),
child: new Form(
key: formKey,
child: new Column(
children: [
new TextFormField(
keyboardType: TextInputType.text,
decoration: new InputDecoration(labelText: 'First Name'),
validator: (val) =>
val.length == 0 ?"Enter FirstName" : null,
onSaved: (val) => this.firstname = val,
),
new TextFormField(
keyboardType: TextInputType.text,
decoration: new InputDecoration(labelText: 'Last Name'),
validator: (val) =>
val.length ==0 ? 'Enter LastName' : null,
onSaved: (val) => this.lastname = val,
),
new TextFormField(
keyboardType: TextInputType.phone,
decoration: new InputDecoration(labelText: 'Mobile No'),
validator: (val) =>
val.length ==0 ? 'Enter Mobile No' : null,
onSaved: (val) => this.mobileno = val,
),
new TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: new InputDecoration(labelText: 'Email Id'),
validator: (val) =>
val.length ==0 ? 'Enter Email Id' : null,
onSaved: (val) => this.emailId = val,
),
new Container(margin: const EdgeInsets.only(top: 10.0),child: new RaisedButton(onPressed: _submit,
child: new Text('Save Employee'),),)
],
),
),
),
);
}
void _submit() {
if (this.formKey.currentState.validate()) {
formKey.currentState.save();
}else{
return null;
}
var employee = Employee(firstname,lastname,mobileno,emailId);
var dbHelper = DBHelper();
dbHelper.saveEmployee(employee);
_showSnackBar("Data saved successfully");
}
void _showSnackBar(String text) {
scaffoldKey.currentState
.showSnackBar(new SnackBar(content: new Text(text)));
}
void navigateToEmployeeList(){
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new MyEmployeeList()),
);
}
}
Descargar
Vamos a descargar el proyecto, o a buscarlo desde github.
| --- |
|---|
Crédito y agradecimiento al creador original del proyecto anterior @payen83
Cómo se ejecuta
- Descargue el proyecto anterior.
- Crea tu aplicación en android studio/visual studio de forma normal.
- Edita el
pubspec.yamlpara añadir las dependencias adecuadas. - Copia y pega los archivos dart de arriba en tu proyecto.
Entonces:
Sólo asegúrate de que tu dispositivo o emulador se está ejecutando y haz clic en el botón run en android studio, automáticamente elegirá el dispositivo e instalará la aplicación.
Aletrnative puede utilizar el terminal o símbolo del sistema. Navega/Cd hasta la página raíz del proyecto y escribe esto:
flutter.bat build apk
Esto construirá el APK que luego puede arrastrar e instalar en su dispositivo. El proceso de construcción en mi máquina toma alrededor de tres minutos que no está mal.