SQFlite is a flutter plugin that is used to store data. Many operations are performed in SQFlite, such as create, delete, and update. This is referred to as CRUD Operations. We may easily store the data in a local database using this method.
Introduction:
In Flutter, there are many different ways to save data, however SQFlite is a very simple plugin to store data locally. SQFlite plugin is compatible with macOS, Android, and iOS. One of the most popular and current packages for linking to SQLite databases in Flutter is SQFLite.
Add Dependency:
In your project, open the pubspec.yaml file and add the following dependencies under the dependencies: sqflite, into, and flutter staggered grid view.
dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 sqflite: ^2.0.0+3 intl: ^0.17.0 flutter_staggered_grid_view: ^0.4.0-nullsafty.3
We utilise sqflite for database storage, intl for DateTime format, and flutter staggered grid view for grid todo display.
Create Database:
Create Database: We must create a database connection in order to access and write data.
And for this, we build a database, and within it, we want to return our database if it already exists; however, if it does not exist, we need to initialise our database, and for that, we create a new file notes. db, and within it, we store database.
Future<Database> get database async { if (_database != null) return _database!; _database = await _initDB('notes.db'); return _database!; }
Initialize Database: To do so, we build a new function that gets the file path and stores our database in our file storage system.
Future<Database> _initDB(String filePath) async { final dbPath = await getDatabasesPath(); final path = join(dbPath, filePath); return await openDatabase(path, version: 1, onCreate: _createDB); }
Database Method: Within openDatabase, we define a _createDB method (). And within this method, which we wish to call the database execute method(), we can include our build table statement and define the structure of our table.
Future _createDB(Database db, int version) async { final idType = 'INTEGER PRIMARY KEY AUTOINCREMENT'; final textType = 'TEXT NOT NULL'; final boolType = 'BOOLEAN NOT NULL'; final integerType = 'INTEGER NOT NULL'; await db.execute(''' CREATE TABLE $tableNotes ( ${NoteFields.id} $idType, ${NoteFields.isImportant} $boolType, ${NoteFields.number} $integerType, ${NoteFields.title} $textType, ${NoteFields.description} $textType, ${NoteFields.time} $textType ) '''); }
Create Model Class:
We build a class called Note, and within it we add all of the fields that we want to store in our database. To store our node, we must first establish a table. As a result, we make table name notes.
class Note { final int? id; final bool isImportant; final int number; final String title; final String description; final DateTime createdTime; const Note({ this.id, required this.isImportant, required this.number, required this.title, required this.description, required this.createdTime, });
as well as every field we wish to develop. To do this, we build a new class called NoteFields and set the field name in there.
CURD Operations:
Create: The Sqflite package offers two methods for holding these operations: using table names and a map containing the data, or using RawSQL queries:
rawInsert:
Future<Note> create(Note note) async { final db = await instance.database; final json = note.toJson(); final columns = '${NoteFields.title}, ${NoteFields.description}, ${NoteFields.time}'; final values = '${json[NoteFields.title]}, ${json[NoteFields.description]}, ${json[NoteFields.time]}'; final id = await db .rawInsert('INSERT INTO table_name ($columns) VALUES ($values)'); return note.copy(id: id); }
Insert:
Future<Note> create(Note note) async { final db = await instance.database; final id = await db.insert(tableNotes, note.toJson()); return note.copy(id: id); }
Read:
In order to pass the id, we create a ReadNote. which we already constructed, and if you send the id within, we may retrieve the note object from our database once more. We first define our database, then add a table (tableNotes), and then we create a function query(). In the NoteFiels class, create a value list and specify the note object you wish to read. Use where and whereArgs to defend against attacks using SQL injection.
Future<Note> readNote(int id) async { final db = await instance.database; final maps = await db.query( tableNotes, columns: NoteFields.values, where: '${NoteFields.id} = ?', whereArgs: [id], ); if (maps.isNotEmpty) { return Note.fromJson(maps.first); } else { throw Exception('ID $id not found'); } }
Update:
We use the update Curd procedure to update our notes. which allows us to update the wording. We pass a note object inside the update method that ER creates. As before, add the database reference and return the update method. Additionally, define the table you want to change, and then send a note object with a JSON object inside.
Future<int> update(Note note) async { final db = await instance.database; return db.update( tableNotes, note.toJson(), where: '${NoteFields.id} = ?', whereArgs: [note.id], ); }
Delete:
When deleting an object, we employ the delete Curd operation. A delete method must be created in order to remove anything (). And then call the db.delete() method, specifying the table to be deleted along with the note object. Finally, we specify the object to be deleted.
Future<int> delete(int id) async { final db = await instance.database; return await db.delete( tableNotes, where: '${NoteFields.id} = ?', whereArgs: [id], ); }
Implementation:
We take a stateful class in the SQFlite demo first. define a list with the name notes and an isLoading bool variable. Then, we construct the method refreshNotes(), and we tell it to refresh readallnotes if isLoading is true (),
Future refreshNotes() async { setState(() => isLoading = true); this.notes = await NotesDatabase.instance.readAllNotes(); setState(() => isLoading = false); }
And then call initstate with this way (). We use the property of the appbar and pass the scaffold in the BuildContext() method. StaggeredGridView is passed to the buildNotes() method, which we supply in the body. countBuilder() In this weight, all produced cards are displayed; otherwise, an empty screen is displayed.
Widget buildNotes() => StaggeredGridView.countBuilder( padding: EdgeInsets.all(8), itemCount: notes.length, staggeredTileBuilder: (index) => StaggeredTile.fit(2), crossAxisCount: 4, mainAxisSpacing: 4, crossAxisSpacing: 4, itemBuilder: (context, index) { final note = notes[index]; return GestureDetector( onTap: () async { await Navigator.of(context).push(MaterialPageRoute( builder: (context) => NoteDetailPage(noteId: note.id!), )); refreshNotes(); }, child: NoteCardWidget(note: note, index: index), ); }, );
We build a FloatingActionButton() at the bottom, which is used to add new notes. When the FloatingActionButton() is clicked, the AddEditNotePage is navigated to ().
We build a form() in the AddEditNotePage() function, where we enter our content, and we pass a button whose name is saved; this button is used to save the text. To do this, we construct a method called buildButton() and check its isFormValid() status there.
Widget buildButton() { final isFormValid = title.isNotEmpty && description.isNotEmpty; return Padding( padding: EdgeInsets.symmetric(vertical: 8, horizontal: 12), child: ElevatedButton( style: ElevatedButton.styleFrom( onPrimary: Colors.white, primary: isFormValid ? null : Colors.grey.shade700, ), onPressed: addOrUpdateNote, child: Text('Save'), ), ); }
Two buttons—one for updating notes and the other for deleting them—are defined in the appbar. We provide a technique called editButton to edit the note (). When we click on this button, we are taken to the edit page, and once we have finished modifying, the page is refreshed.
Widget editButton() => IconButton( icon: Icon(Icons.edit_outlined), onPressed: () async { if (isLoading) return; await Navigator.of(context).push(MaterialPageRoute( builder: (context) => AddEditNotePage(note: note), )); refreshNote(); });
Additionally, a function called deleteButton() that deletes the instance of the note is created for the other button that is used for deleting notes.
Widget deleteButton() => IconButton( icon: Icon(Icons.delete), onPressed: () async { await NotesDatabase.instance.delete(widget.noteId); Navigator.of(context).pop(); }, );
Conclusion:
What SQFlite in Flutter is and how to use it in a Flutter have been covered in this article. We can deliver several curd orations by utilising. Additionally, adding or removing databases locally is simple.
Thank you for reading this article.