Flutter Base de Données

Le module Flutter permettant de gérer une base de donnée est SQFLITE (SQL Flutter Lite)

1°) Ajout de la dépendance :

Dans le fichier pubspec.yaml, ajouter sous sdk: flutter

Ce qui donne :
dependencies:
  flutter:
    sdk: flutter
  sqflite: ^1.3.2+2
  path_provider: ^1.6.27

2°) Création du fichier gérant la base de données :

Exemple, création d’une base de données « RADIOS » qui possédera 2 tables « CHAINES » et « FAVORIS » et les fonctions nécessaires pour créer la base et les tables, pour supprimer la table « FAVORIS » pour lister le contenu des enregistrements des deux tables et pour insérer dans la table « FAVORIS » une série d’enregistrements de la table « CHAINES » tagués.

3°) Affichage de la liste de toutes les radios

Comptage du nombre de ligne de la table :

Future countChainesTable() async {
  int count;
  var dbFav = await db;
  count = Sqflite.firstIntValue(
      await dbFav.rawQuery('SELECT COUNT(*) FROM RadioChaines'));
  return (count);
}

La requête SQL récupérant toutes les radios est la suivante :

/// Retourne toutes les chaines de radios au format de liste StationRadio
Future getAllChaines() async {
var db = await SqliteDB().db;
var result = await db.rawQuery("SELECT id, title FROM RadioChaines");
return result;
}

La classe permettant d’afficher une liste comportant l’ID de la station et le nom de la radio est la suivante :

class StationRadio {
  int id;
  String title;
  StationRadio(this.id, this.title);
  @override
  String toString() {
    return '{ ${this.id}, ${this.title} }';
  }
}

La récupération de la liste avec le couple ID ; RADIO est :

//-- Création de la liste contenant toutes les radios disponibles
_counter = await db.countChainesTable();
var resultat;
if (_counter > 0) {
  resultat = await db.getAllChaines();
  print(resultat); // Pour DEBUG
  for (int i = 0; i < _counter; i++) {
    Map<String, dynamic> tteradios = resultat[i];
    print(tteradios['id']);
    print(tteradios['title']);
    ToutesRadios.add(StationRadio(tteradios['id'],tteradios['title']));
  }
}

Mise à jour de la table à partir d’une liste d’éléments :

Future UpdateFavorites(List SelectedRadio) async {
if (SelectedRadio == null || SelectedRadio.isEmpty) {
return 0;
}
var db = await SqliteDB().db;
await db
.rawQuery("UPDATE RadioChaines SET isselected ='0' WHERE isselected='1'");

for (int i = 0; i < SelectedRadio.length; i++) {
  await db.rawQuery("UPDATE RadioChaines SET isselected ='1' WHERE id='" +
      SelectedRadio[i].id.toString()+"'");
}
return SelectedRadio.length;}

Références :

https://medium.com/flutter-community/using-sqlite-in-flutter-187c1a82e8b

https://www.javacodegeeks.com/2020/06/using-sqlite-in-flutter-tutorial.html

https://stackoverflow.com/questions/55038667/error-a-value-of-type-dynamic-cant-be-assigned-to-a-variable-of-type-string

https://stackoverflow.com/questions/60221922/map-of-object-containing-a-listobject-for-sqlite

https://stackoverflow.com/questions/54102043/how-to-do-a-database-update-with-sqflite-in-flutter

2°) Création des répertoires et des fichiers de paramétrage :

Sous lib, créer le répertoire database, dans database créez un fichier database_helper.dart qui va contenir les méthoses utiles pour manipuler les données de la base.

import 'dart:async';
import 'dart:io' as io;

import 'package:flutter_app_db/database/record.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

class DatabaseHelper {
static final DatabaseHelper _instance = new DatabaseHelper.internal();
factory DatabaseHelper() => _instance;
static Database _db;

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

DatabaseHelper.internal();

initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "main.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 User(id INTEGER PRIMARY KEY, firstname TEXT, lastname TEXT, dob TEXT)");
}

Future<int> saveUser(User user) async {
var dbClient = await db;
int res = await dbClient.insert("User", user.toMap());
return res;
}

Future<List<User>> getUser() async {
var dbClient = await db;
List<Map> list = await dbClient.rawQuery('SELECT * FROM User');
List<User> employees = new List();
for (int i = 0; i < list.length; i++) {
var user =
new User(list[i]["firstname"], list[i]["lastname"], list[i]["dob"]);
user.setUserId(list[i]["id"]);
employees.add(user);
}
print(employees.length);
return employees;
}

Future<int> deleteUsers(User user) async {
var dbClient = await db;

int res =
await dbClient.rawDelete('DELETE FROM User WHERE id = ?', [user.id]);
return res;
}

Future<bool> update(User user) async {
var dbClient = await db;
int res = await dbClient.update("User", user.toMap(),
where: "id = ?", whereArgs: <int>[user.id]);
return res > 0 ? true : false;
}
}

Il est possible de déclarer plusieurs tables dans la base de données

 void _createDb(Database db, int newVersion) async {
 await db.execute('''
   create table $carTable (
    $columnCarId integer primary key autoincrement,
    $columnCarTitle text not null
   )''');
 await db.execute('''
   create table $userTable(
    $userId integer primary key autoincrement,
    $name text not null
   )''');
  }

Dans le répertoire database, créez un fichier record.dart qui contiendra la classe définissant un enregistrement dans la table

class User {

  int id;
  String _firstName;
  String _lastName;
  String _dob;

  User(this._firstName, this._lastName, this._dob);

  User.map(dynamic obj) {
    this._firstName = obj["firstname"];
    this._lastName = obj["lastname"];
    this._dob = obj["dob"];
  }

  String get firstName => _firstName;

  String get lastName => _lastName;

  String get dob => _dob;

  Map<String, dynamic> toMap() {
    var map = new Map<String, dynamic>();
    map["firstname"] = _firstName;
    map["lastname"] = _lastName;
    map["dob"] = _dob;
    return map;
  }
  void setUserId(int id) {
    this.id = id;
  }
}

3°) Appel :

main.dart

avec list view list.dart

4°) Importation / édition d’une base existante :

a) méthode avec Android Studio :

Chargez dans Android Studio l’application qui a une base de données et connectez votre téléphone avec l’application installée.

  • S’assurer qu’ADB est bien fonctionnel
    • Open File -> Project Structure;
    • In Project, select valid Project SDK;
    • In Modules -> myapp_android -> Dependencies, select a valid Module SDK
    • Then close AS, kill adb process in Task Manager, do adb start-server in command line and start AS(cf https://github.com/flutter/flutter/issues/55557
  • Ouvrez Device File Explorer 
    • Allez dans data\data\<<Nom_de_l’application>>
    • Téléchargez la base
    • Editez la via un éditeur
    • Puis Upload

b) Via programmation :

import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import "package:path/path.dart";
import 'package:sqflite/sqflite.dart';
import 'dart:io' as io;

class SqliteDB {
  static const NEW_DB_VERSION = 2;
  static final SqliteDB _instance = new SqliteDB.internal();

  factory SqliteDB() => _instance;
  static Database _db;

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

  SqliteDB.internal();

  ////////////////////////////////////////////////////////////////////////////////////////////////:

  Future<Database> initDb() async {

    final databasesPath = await getDatabasesPath();
    final path = join(databasesPath, "database.db");

    var db = await openDatabase(path);

    //if database does not exist yet it will return version 0
    if (await db.getVersion() < NEW_DB_VERSION) {

      db.close();

      //delete the old database so you can copy the new one
      await deleteDatabase(path);

      try {
        await Directory(dirname(path)).create(recursive: true);
      } catch (_) {}

      //copy db from assets to database folder
      ByteData data = await rootBundle.load("assets/db/radios.db");
      List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
      await io.File(path).writeAsBytes(bytes, flush: true);

      //open the newly created db
      db = await openDatabase(path);

      //set the new version to the copied db so you do not need to do it manually on your bundled database.db
      db.setVersion(NEW_DB_VERSION);

    }
    return db;
  }

https://stackoverflow.com/questions/60458746/is-there-a-way-to-check-the-database-version-in-a-flutter-app-using-sqflite

https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md

Références :

https://www.developerlibs.com/2018/07/flutter-sqlite-database-example.html

https://www.tutorialspoint.com/flutter/flutter_database_concepts.htm

https://medium.com/flutter-community/using-sqlite-in-flutter-187c1a82e8b

https://www.javacodegeeks.com/2020/06/using-sqlite-in-flutter-tutorial.html

Articles récents
Commentaires récents
fatima dans Bienvenue !
AdminDroid dans Bienvenue !
fatima dans Bienvenue !
Archives
Catégories
%d blogueurs aiment cette page :