Step 1: Create a Flutter project
If you haven't installed Flutter yet, follow the instructions on the official Flutter website to do so. After that, create a new Flutter project using the following command:
flutter create data_synchronization
cd data_synchronization
Step 2: Set Up dependencies
Add the plugins to your pubspec.yaml file and run flutter pub get
to install the dependencies as shown below.
dependencies:
path_provider: ^2.0.9
sqflite: ^2.0.2
firebase_core: ^2.8.0
cloud_firestore:
firebase_storage: ^11.0.0
Step 3: Create a Model
Step 4: Create your sqflite database management file
import 'dart:io';
import 'package:data_synchronization/person.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static const _databaseName = 'MyDatabase.db';
// ignore: constant_identifier_names
static const int DB_VERSION = 1;
//singleton class
DatabaseHelper._();
static final DatabaseHelper instance = DatabaseHelper._();
Database? _database;
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDatabase();
return _database!;
}
//init database
_initDatabase() async {
Directory dataDirectory = await getApplicationDocumentsDirectory();
String dbPath = join(dataDirectory.path, _databaseName);
return await openDatabase(dbPath,
version: DB_VERSION, onCreate: _onCreateDB);
}
Future _onCreateDB(Database db, int version) async {
//create tables
await db.execute('''
CREATE TABLE ${Person.tblTable}(
${Person.colId} INTEGER PRIMARY KEY AUTOINCREMENT,
${Person.colName} TEXT,
${Person.colAge} INTEGER
)
''');
}
//Data - insert
Future<int> insertData(Person blog) async {
Database db = await database;
return await db.insert(Person.tblTable, blog.toMap());
}
//Data - update
Future<int> updateDatag(Person blog) async {
final db = await database;
var result = await db.update(Person.tblTable, blog.toMap(),
where: "${Person.colId} = ?", whereArgs: [blog.id]);
return result;
}
//Data - retrieve all
Future<List<Person>> fetchDatas() async {
Database db = await database;
List blogs = await db.query(Person.tblTable);
return blogs.isEmpty
? []
: blogs.map((x) => Person.fromMap(x)).toList();
}
// ignore: body_might_complete_normally_nullable
Future<int?> closeDb() async {
var dbClient = await database;
await dbClient.close();
}
deleteAll() async {
final dbClient = await database;
dbClient.rawDelete("Delete from ${Person.tblTable}");
}
}
Step 5: Create a AddUser Widget
Nous configurons ici nos bases de données sqflite et mettons en place des requêtes pour ajouter, afficher, modifier et supprimer des données sqflite.
import 'package:data_synchronization/db_helper.dart';
import 'package:data_synchronization/person.dart';
import 'package:flutter/material.dart';
// Widget de formulaire pour saisir les données
class AddPersonForm extends StatefulWidget {
@override
_AddPersonFormState createState() => _AddPersonFormState();
}
class _AddPersonFormState extends State<AddPersonForm> {
bool isLoad = false;
final DatabaseHelper _dbHelper = DatabaseHelper.instance;
final _formKey = GlobalKey<FormState>();
late TextEditingController _nameController;
late TextEditingController _ageController;
@override
void initState() {
super.initState();
_nameController = TextEditingController();
_ageController = TextEditingController();
}
@override
void dispose() {
_nameController.dispose();
_ageController.dispose();
super.dispose();
}
// Méthode pour enregistrer les données dans SQLite
Future<void> _saveToSqflite() async {
if (_formKey.currentState!.validate()) {
await _dbHelper.insertData(
Person(
name:_nameController.text.trim(),
age: int.parse(_ageController.text.trim())
)
);
_nameController.clear();
_ageController.clear();
// ignore: use_build_context_synchronously
Navigator.pop(context);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Add User"),
centerTitle: true,
),
body: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(labelText: 'Name'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter a name';
}
return null;
},
),
TextFormField(
controller: _ageController,
decoration: const InputDecoration(labelText: 'Age'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter an age';
}
if (int.tryParse(value) == null) {
return 'Please enter a valid age';
}
return null;
},
),
ElevatedButton(
onPressed: _saveToSqflite,
child: const Text('Save'),
),
],
),
),
);
}
}
Step 5: Create a HomeScreen Widget
In this view, we'll then display the data and create two functions to synchronize data from saqflite to Firebase and from Firebase to sqflite.
import 'package:data_synchronization/db_helper.dart';
import 'package:data_synchronization/person.dart';
import 'package:data_synchronization/add_user.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
DatabaseHelper? _dbHelper;
late List<Person> _blogs;
bool _isLoading = true;
bool _isSynch = false;
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
@override
void initState() {
super.initState();
_dbHelper = DatabaseHelper.instance;
_getBloges();
}
Future _getBloges() async {
List<Person> _blog = await _dbHelper!.fetchDatas();
setState(() {
_blogs = _blog;
_isLoading = false;
});
}
Future<Null> _refresh() async {
List<Person> _blog = await _dbHelper!.fetchDatas();
setState(() {
_blogs = _blog;
});
return null;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Home Page"),
actions: [
GestureDetector(
onTap: () async{
await _dbHelper!.deleteAll();
setState(() {
_refresh();
});
},
child: const Icon(Icons.delete_outline),
),
const SizedBox(width: 10),
myPopMenu()
],
),
body: RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: _refresh,
child: (_isLoading || _isSynch)
?
const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.pink),
)
)
: _blogs.isEmpty
?
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Aucun résultat trouvé",
),
GestureDetector(
onTap: (){
_refresh();
},
child: const Padding(
padding: EdgeInsets.only(top: 15),
child: Icon(Icons.refresh,size: 40,color: Colors.black45,),
),
)
],
),
)
:
ListView.builder(
shrinkWrap: true,
itemCount: _blogs.length,
itemBuilder: (context, index){
return Padding(
padding: const EdgeInsets.only(top: 15, left: 2, right: 2),
child: ListTile(
leading: CircleAvatar(
radius: 35,
backgroundColor: Colors.pink,
child: Center(
child: Text("${_blogs[index].id}",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15
,color: Colors.white
)
),
),
),
title: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('${_blogs[index].name}',
style: const TextStyle(fontWeight: FontWeight.bold)
),
const SizedBox(height: 08),
Text('${_blogs[index].age}')
],
),
)
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => _navigateToAddUser(context),
child: const Icon(Icons.add_outlined),
)
);
}
Widget myPopMenu() {
return PopupMenuButton(
onSelected: (value) {
if(value==1){
syncSqfliteToFirebase();
}else if(value==2){
syncFirebaseToSqflite();
}
},
itemBuilder: (context) => [
const PopupMenuItem(
value: 1,
child: Text('Synchronisation Sqflite => Firebase',maxLines: 2)),
const PopupMenuItem(
value: 2,
child: Text('Synchronisation Firebase => Sqflite',maxLines: 2)),
]);
}
void _navigateToAddUser(BuildContext context){
Navigator.push(context, MaterialPageRoute(
builder: (contex)=> AddPersonForm())).then((value) {
setState(() {
_refresh();
});
});
}
// Method to synchronize data from SQLite to Firebase
Future<void> syncSqfliteToFirebase() async {
setState(() {
_isSynch = true;
});
// SQLite data retrieval
List<Person> allpersonnes = await _dbHelper!.fetchDatas();
List<Person> newData = [];
// Retrieve existing data from Firebase
QuerySnapshot firebaseData =
await FirebaseFirestore.instance.collection('firebase_tab').get();
// Check for duplicate data
List<String> firebaseIds = firebaseData.docs.map((doc) => doc.id).toList();
for (var data in allpersonnes) {
if (!firebaseIds.contains(data.id)) {
newData.add(
Person(
id: data.id,
name: data.name,
age: data.age,
),
);
}
}
// Send new data to Firebase
CollectionReference collection =
FirebaseFirestore.instance.collection('firebase_tab');
newData.forEach((person) {
collection.doc(person.id).set(person.toJson());
});
setState(() {
_isSynch = false;
});
}
// Method to sync data from Firebase to SQLite
Future<void> syncFirebaseToSqflite() async {
setState(() {
_isSynch = true;
});
// Retrieving data from Firebase
QuerySnapshot firebaseData =
await FirebaseFirestore.instance.collection('firebase_tab').get();
List<Person> firebasePeople =
firebaseData.docs.map((doc) => Person.fromSnapshot(doc)).toList();
// Recovering existing data in SQLite
List<Person> allpersonnes = await _dbHelper!.fetchDatas();
// Check for duplicate data
List sqliteIds = allpersonnes.map((data) => data.id).toList();
List<Person> newData = [];
for (var person in firebasePeople) {
if (!sqliteIds.contains(person.id)) {
print("oui oui ${person.name}");
newData.add(person);
}else{
print("Nononon ${person.name}");
}
}
//Inserting new data in SQLite
for (var person in newData) {
print(person.name);
_dbHelper!.insertData(person);
}
setState(() {
_refresh();
_isSynch = false;
});
}
}
Don't forget to leave a comment if you enjoyed
Top comments (1)
Wow. That's really great