🍼 Baby Steps: Flutter To‑Do App with SQLite
Follow these tiny, exact steps to build a local To‑Do app in Flutter. After each micro-step, do the quick check — then continue. Perfect for beginners and classrooms.
Overview
This project stores tasks locally using SQLite via the sqflite package. You'll implement adding, listing, marking done, and deleting tasks. Each section below is split into micro-steps with code and checks.
STEP 0 — Prepare your environment
0.1 Install Flutter (if you haven't)
Follow: https://flutter.dev/docs/get-started/install
Flutter 3.x.x.0.2 Validate setup
flutter doctor
STEP 1 — Create the Flutter project (micro)
1.1 Create project folder
flutter create todo_app
todo_app exists in your current directory.1.2 Enter the project
cd todo_app
todo_app (use pwd to confirm).1.3 Open in editor
code . # optional — opens VS Code
lib/, pubspec.yaml in the editor.STEP 2 — Add required packages
2.1 Add sqflite
flutter pub add sqflite
Changed 1 dependency or similar output.2.2 Add path_provider
flutter pub add path_provider
sqflite and path_provider now appear under dependencies in pubspec.yaml.2.3 Verify packages
flutter pub get
flutter pub deps | grep sqflite
flutter pub deps | grep path_provider
grep commands show the packages and versions — or on Windows use flutter pub deps and inspect the output manually.STEP 3 — Create the database helper (very small coding steps)
3.1 Make folder for DB helper
mkdir -p lib/database
lib/database folder exists in the project tree.3.2 Create the file
touch lib/database/db_helper.dart
db_helper.dart is visible in your editor under lib/database.3.3 Paste imports
import 'dart:io';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
flutter pub get).3.4 Add DBHelper skeleton
class DBHelper {
static Database? _database;
static final DBHelper instance = DBHelper._init();
DBHelper._init();
}
3.5 Add database getter + init
Future get database async {
if (_database != null) return _database!;
_database = await _initDB('todo.db');
return _database!;
}
Future _initDB(String filePath) async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, filePath);
return await openDatabase(path, version: 1, onCreate: _createDB);
}
flutter analyze — there should be no unresolved references to getApplicationDocumentsDirectory or openDatabase.3.6 Add table creation SQL
Future _createDB(Database db, int version) async {
await db.execute('''
CREATE TABLE todos(
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
isDone INTEGER NOT NULL
)
''');
}
3.7 Add CRUD methods
Future insert(Map row) async {
final db = await instance.database;
return await db.insert('todos', row);
}
Future>> queryAll() async {
final db = await instance.database;
return await db.query('todos', orderBy: 'id DESC');
}
Future update(Map row) async {
final db = await instance.database;
int id = row['id'];
return await db.update('todos', row, where: 'id = ?', whereArgs: [id]);
}
Future delete(int id) async {
final db = await instance.database;
return await db.delete('todos', where: 'id = ?', whereArgs: [id]);
}
flutter analyze — no errors in this file and methods are accessible via DBHelper.instance.STEP 4 — Build the UI (tiny coding steps)
4.1 Open lib/main.dart
open lib/main.dart
4.2 Minimal app shell (paste and run)
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold(body: Center(child: Text('Hello'))));
}
}
4.3 Add Scaffold + AppBar
Scaffold(
appBar: AppBar(title: const Text('My To-Do List')),
body: Column(children: []),
)
4.4 Add input row (TextField + Add button)
Padding(
padding: const EdgeInsets.all(8),
child: Row(children: [
Expanded(child: TextField(controller: _controller, decoration: InputDecoration(labelText: 'Enter Task', border: OutlineInputBorder()))),
IconButton(icon: Icon(Icons.add), onPressed: _addTodo)
]),
)
4.5 Add list placeholder
Expanded(child: ListView(children: [Text('task 1'), Text('task 2')]))
4.6 Paste the full final main.dart (paste and run)
import 'package:flutter/material.dart';
import 'database/db_helper.dart';
void main() { runApp(const TodoApp()); }
class TodoApp extends StatelessWidget { const TodoApp({super.key});
@override Widget build(BuildContext context) {
return MaterialApp(title: 'Flutter To-Do', theme: ThemeData(primarySwatch: Colors.blue), home: const TodoHome());
}
}
class TodoHome extends StatefulWidget { const TodoHome({super.key});
@override State createState() => _TodoHomeState();
}
class _TodoHomeState extends State {
final TextEditingController _controller = TextEditingController();
List
STEP 5 — Run & test (tiny steps)
5.1 Run the app
flutter run
5.2 Add a task
Type in the field and press the + button
5.3 Confirm persistence
Stop the app and run flutter run again
Diagrams & visuals
Diagrams created for this tutorial (upload them to Blogger and replace the image URLs):
Tip: Use the DFD for architecture explanation, Flowchart for control flow, ER for data model, and UML for class details.
Troubleshooting & tips (tiny)
T1 — DB file not found
getApplicationDocumentsDirectory().T2 — Hot reload not reflecting DB changes
T3 — Analyzer & build errors
Download / Clone
You can download a ready ZIP or clone a Git repo. I can create the Git repo for you if you want — tell me and I’ll push these files to GitHub (or provide a ZIP).
(Replace these placeholders with your repo or download URLs before publishing.)
0 Comments