100
30 mars 2019

Base de données dans Flutter

banniere base de données dans flutter

Base de données dans Flutter

Très importantes dans une application mobile, les bases de données nous permettent de stocker des informations sans avoir systématiquement besoin d’une connexion internet. En clair, les bases de données offrent la possibilité de stocker des actions faites par l’utilisateur. Dans notre app Flutter, nous allons utiliser le super plugin sqflite.

Sqflite prend en charge à la fois Android et iOS, ce qui est parfait pour nous. Comme toujours, nous ne verrons que les bases dans cet article, largement suffisantes pour notre exercice.

Créer une simple Base de données dans Flutter

Dans Flutter, toujours le même principe; on ajoute d’abord le package qui va nous servir. Cette fois-ci, nous allons utiliser le plugin sqflite que l’on trouve dans pub.dartlang.org.
Dans un premier temps, ajoutez la dépendance dans votre fichier pubspec.yaml et faites un get packages.

1
sqflite: ^1.1.0

Dans ce premier exemple, nous créons une base de données dans Flutter “festival”, qui a une table Artiste.
Très simple pour l’instant ! Nous avons une fonction pour initialiser la base de données, créer notre table, et deux autres fonctions pour ajouter un artiste et compter le nombre d’entrées en base.
Bien entendu, nous allons améliorer tout cela par la suite.

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
import 'package:flutter/material.dart';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: "hmwkapp",
debugShowCheckedModeBanner: false,
home: new MyHomePage(),
);
}
}

class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

int countNb = 0;
Database database = null;

@override
void initState(){
super.initState();
_openCreateDatabase();
}

Future<void> _openCreateDatabase() async {

var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'festival.db');

database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute('CREATE TABLE Artiste (id INTEGER PRIMARY KEY, name TEXT)');
});
}

_addArtisteDatabase() async {
await database.transaction((txn) async {
await txn.rawInsert('INSERT INTO Artiste(name) VALUES("Alborosie")');
});
}

_getArtisteDatabase() async {
List<Map> list = await database.rawQuery('SELECT * FROM Artiste');
setState(() {
countNb = list.length;
});
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text('hmwkapp'),
),
body: new Center(
child: new Column(
children: <Widget>[
new IconButton(
icon: Icon(Icons.add),
onPressed: () {
_addArtisteDatabase();
},
),
new IconButton(
icon: Icon(Icons.remove_red_eye),
onPressed: () {
_getArtisteDatabase();
},
),
new Text("nb entrer dans la base de donnée : " + countNb.toString())
],
)
)
);
}
}

Travailler avec des Object et des Helper

Maintenant, nous allons séparer un peu nos éléments. Le premier exemple fonctionne très bien si l’on a uniquement une table utile dans une seule vue. En revanche, si l’on souhaite avoir une base de données plus importante avec plusieurs tables, le mieux reste alors de structurer notre code.
Nous allons ainsi créer un object Artiste, et une class databaseHelper pour notre base de données dans Flutter. On pourrait imaginer que l’on récupère une liste d’artistes depuis un flux json et qu’on souhaite le sauvegarder dans une base de données interne de notre application mobile.

Notre object Artiste

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
class Artiste {

int _id;
String _image;
String _title;

Artiste(String image, String title) {
this._image = image;
this._title = title;
}

Artiste.map(dynamic obj) {
this._id = obj['id'];
this._image = obj['image'];
this._title = obj['title'];
}

int get id => _id;
String get title => _title;
String get image => _image;

Map<String, dynamic> toMap() {
var map = new Map<String, dynamic>();
if (_id != null) {
map['id'] = _id;
}
map['title'] = _title;
map['image'] = _image;

return map;
}

Artiste.fromMap(Map<String, dynamic> map) {
this._id = map['id'];
this._title = map['title'];
this._image = map['image'];
}
}

Une fois notre class Artiste créée, nous allons faire notre class databaseHelper

Notre class est très basique : on créé une fonction : init, create, close
Dans la fonction create, on ajoutera toutes nos tables, si on en a plusieurs.

Ensuite, nous créons nos fonctions spécifiques à notre table Artiste : addArtiste, getAllArtistes, getArtiste, countArtistes, deleteArtiste, updateArtiste.
On créera par la suite toutes ces fonctions pour chaque table dans notre helper.

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
import 'dart:async';

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

import 'artistes.dart';
import 'event.dart';

class DatabaseHelper {

static final DatabaseHelper _instance = new DatabaseHelper.internal();

factory DatabaseHelper() => _instance;

final String tableArtiste = 'artisteTable';
final String columnArtisteId = 'id';
final String columnArtisteTitle = 'title';
final String columnArtisteImage = 'image';

static Database _db;

DatabaseHelper.internal();

Future<Database> get db async {
if (_db != null) {
return _db;
}
_db = await initDb();

return _db;
}

initDb() async {
String databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'festival.db');

var db = await openDatabase(path, version: 1, onCreate: _onCreate);
return db;
}

void _onCreate(Database db, int newVersion) async {
await db.execute('CREATE TABLE $tableArtiste($columnArtisteId INTEGER PRIMARY KEY, $columnArtisteTitle TEXT, $columnArtisteImage TEXT)');
}

/*
void _onDelete() async {
String databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'festival.db');
await deleteDatabase(path); // just for testing
}
*/


Future close() async {
var dbClient = await db;
return dbClient.close();
}

// ARTISTES //

Future<int> saveArtiste(Artiste artiste) async {
var dbClient = await db;
var result = await dbClient.insert(tableArtiste, artiste.toMap());
// var result = await dbClient.rawInsert('INSERT INTO $tabletableArtiste (columnArtisteTitle, columnArtisteImage) VALUES (\'${artiste.title}\', \'${artiste.image}\')');

return result;
}

Future<List> getAllArtistes() async {
var dbClient = await db;
var result = await dbClient.query(tableArtiste, columns: [columnArtisteId, columnArtisteTitle, columnArtisteImage]);
// var result = await dbClient.rawQuery('SELECT * FROM tableArtiste');

return result.toList();
}

Future<int> getCount() async {
var dbClient = await db;
return Sqflite.firstIntValue(await dbClient.rawQuery('SELECT COUNT(*) FROM $tableArtiste'));
}

Future<Artiste> getArtiste(int id) async {
var dbClient = await db;
List<Map> result = await dbClient.query(tableArtiste,
columns: [columnArtisteId, columnArtisteTitle, columnArtisteImage],
where: '$columnArtisteId = ?',
whereArgs: [id]);
// var result = await dbClient.rawQuery('SELECT * FROM $tableArtiste WHERE $columnArtisteId = $id');

if (result.length > 0) {
return new Artiste.fromMap(result.first);
}

return null;
}

Future<int> deleteArtiste(int id) async {
var dbClient = await db;
return await dbClient.delete(tableArtiste, where: '$columnArtisteId = ?', whereArgs: [id]);
// return await dbClient.rawDelete('DELETE FROM $tableArtiste WHERE $columnArtisteId = $id');
}

Future<int> updateArtiste(Artiste artiste) async {
var dbClient = await db;
return await dbClient.update(tableArtiste, artiste.toMap(), where: "$columnArtisteId = ?", whereArgs: [artiste.id]);
// return await dbClient.rawUpdate(
// 'UPDATE $tableArtiste SET $columnArtisteTitle = \'${artiste.title}\', $columnArtisteImage = \'${artiste.image}\' WHERE $columnArtisteId = ${artiste.id}');
}

}

Pour finir, il nous suffit d’importer nos class pour les utiliser dans le main.

1
2
import 'artistes.dart';
import 'database_helper.dart';

Voilà pour un exemple de fonction.

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
List artistesList;
var db;

int count = 0;

@override
void initState(){
super.initState();

db = new DatabaseHelper();
}

@protected
void dispose() async{
await db.close();
}

_addArtiste() async{
await db.saveArtiste(new Artiste("Alborosie", "https://musikplease.com/wp-content/uploads/sites/17/2016/08/Alborosie_Freedom_Fyah.jpg"));
}

_updateArtiste(Artiste artiste) async{
await db.updateArtiste(artiste);
}

_deleteArtiste(int idArtiste) async{
await db.deleteArtiste(idArtiste);
}

_getAllArtistes() async{
artistesList = await db.getAllArsites();
}

_getArtistes(int idArtiste) async{
Artiste artiste = await db.getNote(idArtiste);
}

_getCountArtistes() async{
int countTemp = await db.getCount();
setState(() {
count = countTemp;
});

}

VOUS EN VOULEZ ENCORE ?

CHANGER D'UNIVERS !