Introduction:
Beginners often create simple apps without considering scalability or maintainability. In this guide, we’ll build a professional, production-ready To-Do app using Riverpod for state management, Hive for persistent storage, and clean architecture principles.
Step 1
Setup Dependencies
dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^2.3.6
hive: ^2.2.3
hive_flutter: ^1.1.0
Step 2
Project Structure (Clean Architecture)
lib/
├─ main.dart
├─ models/
│ └─ task.dart
├─ providers/
│ └─ task_provider.dart
├─ services/
│ └─ task_service.dart
├─ screens/
│ └─ todo_home.dart
This separation makes the app scalable, testable, and maintainable.
Step 3
Create the Task Model
import 'package:hive/hive.dart';
part 'task.g.dart';
@HiveType(typeId: 0)
class Task extends HiveObject {
@HiveField(0)
String title;
@HiveField(1)
bool completed;
Task({required this.title, this.completed = false});
}
Use build_runner to generate Hive adapters:
flutter pub run build_runner build
Step 4
Create Task Service (Handles Data & Persistence)
import 'package:hive_flutter/hive_flutter.dart';
import '../models/task.dart';
class TaskService {
static const String boxName = 'tasksBox';
late Box _box;
Future init() async {
_box = await Hive.openBox(boxName);
}
List getTasks() => _box.values.toList();
Future addTask(Task task) async => await _box.add(task);
Future updateTask(int index, Task task) async => await _box.putAt(index, task);
Future deleteTask(int index) async => await _box.deleteAt(index);
}
Step 5
Create Riverpod Provider
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/task.dart';
import '../services/task_service.dart';
final taskServiceProvider = Provider((ref) => TaskService());
final tasksProvider = StateNotifierProvider>((ref) {
final service = ref.watch(taskServiceProvider);
return TasksNotifier(service);
});
class TasksNotifier extends StateNotifier> {
final TaskService _service;
TasksNotifier(this._service) : super([]) {
loadTasks();
}
Future loadTasks() async {
state = _service.getTasks();
}
Future addTask(String title) async {
final task = Task(title: title);
await _service.addTask(task);
state = [...state, task];
}
Future toggleComplete(int index) async {
final task = state[index];
task.completed = !task.completed;
await _service.updateTask(index, task);
state = [...state];
}
Future deleteTask(int index) async {
await _service.deleteTask(index);
state = [...state]..removeAt(index);
}
}
Step 6:
Build the UI (TodoHome Screen)
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../providers/task_provider.dart';
class TodoHome extends ConsumerWidget {
final TextEditingController controller = TextEditingController();
@override
Widget build(BuildContext context, WidgetRef ref) {
final tasks = ref.watch(tasksProvider);
return Scaffold(
appBar: AppBar(title: Text("Advanced To-Do App")),
body: Column(
children: [
Padding(
padding: EdgeInsets.all(10),
child: TextField(
controller: controller,
decoration: InputDecoration(labelText: "Enter a task"),
),
),
ElevatedButton(
onPressed: () {
ref.read(tasksProvider.notifier).addTask(controller.text);
controller.clear();
},
child: Text("Add Task"),
),
Expanded(
child: ListView.builder(
itemCount: tasks.length,
itemBuilder: (_, index) {
final task = tasks[index];
return ListTile(
title: Text(
task.title,
style: TextStyle(
decoration: task.completed ? TextDecoration.lineThrough : null,
),
),
leading: Checkbox(
value: task.completed,
onChanged: (_) => ref.read(tasksProvider.notifier).toggleComplete(index),
),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => ref.read(tasksProvider.notifier).deleteTask(index),
),
);
},
),
),
],
),
);
}
}
Step 7: Why This Is Pro-Level
Riverpod → Safer, testable, and scalable state management.
Clean Architecture → Separate UI, providers, services, and models.
Persistent storage → Hive ensures data persists across app restarts.
Error handling & async operations → Prepares app for real-world scenarios.
Step 8: Next Enhancements for a Real-World App
Add user authentication with Firebase.
Sync tasks across devices with cloud storage.
Implement push notifications for task reminders.
Add animations & theming for production-quality UX.
Top comments (0)