Data management is at the core of every mobile application in the quick-paced world of app development today. Despite the popularity of cloud-based solutions like Firebase, SQLite excels when you need a straightforward offline local storage solution.
This comprehensive guide will teach you how to create a fully functional Flutter application that is integrated with SQLite. Without an internet connection, you will be able to create, read, update, and delete data (CRUD) locally on the user’s device.
This tutorial will provide you with a solid foundation for working with local databases in your apps, regardless of your level of experience as a Flutter developer.
🧠 What You’ll Discover
After following this tutorial, you will be able to:
- Install SQLite in your Flutter project
- Make local tables and a database.
- Add, edit, and remove data
- Present data in a clear, user-friendly interface.
- Use Snackbars and validation to display user feedback.
This project is straightforward yet useful: you will create a small “Dog Database App” that stores dog names and ages locally on the device.
🛠️ Prerequisites
Before we start, make sure you have:
- Flutter SDK installed (any recent stable version)
- Android Studio, VS Code, or another IDE
- Basic understanding of Dart and Flutter widgets
If you’ve never used SQLite before, don’t worry. This tutorial explains everything clearly and in a step-by-step manner.
⚙️ Step 1: Create a New Flutter Project
Open your terminal or IDE and run:
- flutter create dog_database_app
- cd dog_database_app
This creates a basic Flutter project structure.
🧩 Step 2: Add Dependencies
You’ll need two main packages:
- sqflite → for SQLite operations
- path → to help define database file paths
Add these lines in your pubspec.yaml file under dependencies:
dependencies:
flutter:
sdk: flutter
sqflite: ^2.3.0
path: ^1.8.0
Then, run:
flutter pub get
This installs the required packages.
🗂️ Step 3: Create the Database Helper
In your lib folder, create a new file named database_helper.dart.
This file will handle all database logic. creating tables, inserting, fetching, updating, and deleting records.
Here’s a clean example:
import ‘package:sqflite/sqflite.dart’;
import ‘package:path/path.dart’;
class DatabaseHelper {
static Database? _database;
static Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDB(‘doggie_database.db’);
return _database!;
}
static Future<Database> _initDB(String filePath) async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, filePath);
return await openDatabase(
path,
version: 1,
onCreate: (db, version) async {
await db.execute(
‘CREATE TABLE dogs(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER)’,
);
},
);
}
static Future<int> insertDog(Map<String, Object?> data) async {
final db = await database;
return await db.insert(‘dogs’, data,
conflictAlgorithm: ConflictAlgorithm.replace);
}
static Future<List<Map<String, Object?>>> getDogs() async {
final db = await database;
return await db.query(‘dogs’);
}
static Future<int> updateDog(Map<String, Object?> data, int id) async {
final db = await database;
return await db.update(‘dogs’, data, where: ‘id = ?’, whereArgs: [id]);
}
static Future<int> deleteDog(int id) async {
final db = await database;
return await db.delete(‘dogs’, where: ‘id = ?’, whereArgs: [id]);
}
}
🐶 Step 4: Create the Model Class
Create a file dog.dart in the lib folder.
class Dog {
final int? id;
final String name;
final int age;
Dog({this.id, required this.name, required this.age});
Map<String, Object?> toMap() {
return {‘id’: id, ‘name’: name, ‘age’: age};
}
factory Dog.fromMap(Map<String, Object?> map) {
return Dog(
id: map[‘id’] as int?,
name: map[‘name’] as String,
age: map[‘age’] as int,
);
}
}
🧱 Step 5: Build the User Interface
Now, open lib/main.dart and replace it with the following structure:
import ‘package:flutter/material.dart’;
import ‘database_helper.dart’;
import ‘dog.dart’;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Dog Database’,
theme: ThemeData(primarySwatch: Colors.teal),
home: const DogListScreen(),
);
}
}
class DogListScreen extends StatefulWidget {
const DogListScreen({super.key});
@override
State<DogListScreen> createState() => _DogListScreenState();
}
class _DogListScreenState extends State<DogListScreen> {
late Future<List<Map<String, Object?>>> dogs;
@override
void initState() {
super.initState();
refreshList();
}
void refreshList() {
setState(() {
dogs = DatabaseHelper.getDogs();
});
}
void _showSnackBar(String message) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(message)));
}
void _openDogForm({Map<String, Object?>? dog}) {
final nameController = TextEditingController(text: dog?[‘name’]?.toString() ?? ”);
final ageController = TextEditingController(text: dog?[‘age’]?.toString() ?? ”);
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text(dog == null ? ‘Add Dog’ : ‘Update Dog’),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(controller: nameController, decoration: const InputDecoration(labelText: ‘Name’)),
TextField(controller: ageController, decoration: const InputDecoration(labelText: ‘Age’), keyboardType: TextInputType.number),
],
),
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text(‘Cancel’)),
ElevatedButton(
onPressed: () async {
final name = nameController.text.trim();
final age = int.tryParse(ageController.text.trim());
if (name.isEmpty || age == null) {
_showSnackBar(‘Please enter valid data.’);
return;
}
if (dog == null) {
await DatabaseHelper.insertDog({‘name’: name, ‘age’: age});
_showSnackBar(‘Dog added successfully!’);
} else {
await DatabaseHelper.updateDog({‘name’: name, ‘age’: age}, dog[‘id’] as int);
_showSnackBar(‘Dog updated successfully!’);
}
Navigator.pop(context);
refreshList();
},
child: Text(dog == null ? ‘Add’ : ‘Update’),
),
],
),
);
}
void _deleteDog(int id) async {
await DatabaseHelper.deleteDog(id);
_showSnackBar(‘Dog deleted successfully!’);
refreshList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text(‘Dog Database’)),
body: FutureBuilder<List<Map<String, Object?>>>(
future: dogs,
builder: (context, snapshot) {
if (!snapshot.hasData) return const Center(child: CircularProgressIndicator());
final data = snapshot.data!;
if (data.isEmpty) return const Center(child: Text(‘No dogs added yet.’));
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
final dog = data[index];
return ListTile(
title: Text(‘${dog[‘name’]} (Age: ${dog[‘age’]})’),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(icon: const Icon(Icons.edit, color: Colors.blue), onPressed: () => _openDogForm(dog: dog)),
IconButton(icon: const Icon(Icons.delete, color: Colors.red), onPressed: () => _deleteDog(dog[‘id’] as int)),
],
),
);
},
);
},
),
floatingActionButton: FloatingActionButton(onPressed: () => _openDogForm(), child: const Icon(Icons.add)),
);
}
}
✅ Step 6: Test Your App
Run your app using:
flutter run
You’ll see a simple interface where you can add dogs, update their age, or delete them — all data is stored locally using SQLite.
🧩 Step 7: Wrap-Up
Congratulations! 🎉
You just built a complete Flutter app using SQLite as a local database.
This approach is ideal for offline apps such as:
- Note-taking or To-Do apps
- Expense trackers
- Contact managers
- Small-scale educational apps
For larger projects or cloud sync, you can later integrate Firebase or REST APIs — but mastering local data storage gives you solid ground to build upon.
Keep experimenting and expanding your project—for example, adding search, sorting, or image storage.
🏁 Final Thoughts
Working with SQLite in Flutter is a skill every app developer should know. It’s lightweight, fast, and works perfectly when your app needs to store structured data locally.
Now that you’ve seen how easy it is, try applying this approach to your own idea—maybe a task list, recipe tracker, or inventory app. Keep learning, keep building, and you’ll master Flutter app development in no time.
