How to Persist Todo App Data in Flutter Using Shared Preferences

โ“ Why Persist Data?

If you close the app now, all tasks disappear โ€” that’s because your Todo list only lives in memory.

To fix this, weโ€™ll use Shared Preferences to save the list to local storage and reload it when the app starts.


๐Ÿงฐ What is Shared Preferences?

Shared Preferences is a Flutter plugin for simple key-value storage on the device.

Itโ€™s ideal for:

  • Small amounts of user data
  • App settings
  • Simple lists (like our Todo list)

โš–๏ธ When to Use It (and When Not To)

โœ… Great For:

  • Saving booleans, strings, numbers
  • Small app data
  • User preferences

โŒ Avoid for:

  • Complex data structures
  • Sensitive data (not encrypted)
  • Large datasets โ†’ use Hive, SQLite, or Isar instead

๐Ÿ› ๏ธ Setting Up Shared Preferences

Step 1: Add the Package

In pubspec.yaml:

dependencies:
shared_preferences: ^2.2.2

Then run:

flutter pub get

๐Ÿ“ฆ Saving Todos to Local Storage

Weโ€™ll serialize the list of Todos into JSON strings and store it.

In your todo_provider.dart:

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';

Save Method

Future<void> saveTodos() async {
final prefs = await SharedPreferences.getInstance();
List<String> todoList = _todos.map((todo) => json.encode({
'id': todo.id,
'title': todo.title,
'isDone': todo.isDone,
})).toList();
await prefs.setStringList('todos', todoList);
}

๐Ÿ” Loading Todos on App Start

Add this method to the provider:

Future<void> loadTodos() async {
final prefs = await SharedPreferences.getInstance();
final List<String>? todoList = prefs.getStringList('todos');

if (todoList != null) {
_todos = todoList.map((todoJson) {
final map = json.decode(todoJson);
return Todo(
id: map['id'],
title: map['title'],
isDone: map['isDone'],
);
}).toList();
notifyListeners();
}
}

Call it in the providerโ€™s constructor or via an init() method in your main screen:

@override
void initState() {
super.initState();
Provider.of<TodoProvider>(context, listen: false).loadTodos();
}

๐Ÿง  Updated Provider Code

Whenever you add, delete, or toggle a todo, call saveTodos() afterward.

void addTodo(String title) {
// existing logic ...
saveTodos();
}

void toggleTodo(String id) {
// existing logic ...
saveTodos();
}

void deleteTodo(String id) {
// existing logic ...
saveTodos();
}

โœ… Complete Example

You now have a fully functional app that:

  • Adds/removes tasks
  • Uses Provider for state
  • Saves data locally
  • Loads persisted todos on app restart

๐Ÿ“ˆ Next Steps

๐Ÿ‘‰ Continue with:
**How to Use Hive for Flutter Offline Storage


๐Ÿ“ฌ Stay in Sync

Get Flutter productivity tips, tutorials, and updates weekly.
Join the FlutterTalk Newsletter โ†’


โœ… TL;DR

  • Use Shared Preferences for small, local data like settings or short lists
  • Serialize data into JSON
  • Rehydrate on app startup
  • Simple, effective, and beginner-friendly!

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.