SharedPreferences in Flutter
SharedPreferences is a Flutter plugin used for storing and retrieving simple key-value data persistently. It is useful when an application needs to remember small pieces of user or application preferences such as login status, theme mode, language selection, onboarding completion, settings, counters, and other simple values.
The shared_preferences package supports simple data types such as int, double, bool, String, and List. The current package also provides SharedPreferencesAsync and SharedPreferencesWithCache; the older SharedPreferences API is considered legacy for new code. :contentReference[oaicite:0]{index=0}
1. What is SharedPreferences?
SharedPreferences provides a simple persistent key-value storage mechanism. Data stored in it can remain available when the application is closed and opened again.
Simple Example
Key Value
--------------------------------
username Manish
isLoggedIn true
age 25
theme dark
Each value is associated with a unique key. The key is used to save, retrieve, update, or remove the corresponding value.
2. Why Use SharedPreferences?
- Store simple application preferences.
- Remember whether a user has completed onboarding.
- Store login or session-related flags.
- Save theme preferences.
- Save language preferences.
- Store simple counters.
- Store small configuration values.
- Persist simple settings between application launches.
3. How SharedPreferences Works
Flutter Application
|
v
shared_preferences Package
|
v
Key-Value Storage
|
v
Platform Storage
|
+-- Android
+-- iOS
+-- Web
+-- Windows
+-- macOS
+-- Linux
The package provides a common Flutter API while using platform-specific persistent storage underneath. The current package supports Android, iOS, Linux, macOS, web, and Windows. :contentReference[oaicite:1]{index=1}
4. Installing SharedPreferences
Add the shared_preferences package to your Flutter project.
flutter pub add shared_preferences
Alternatively, add it manually to pubspec.yaml.
dependencies:
flutter:
sdk: flutter
shared_preferences: ^2.5.5
The package version changes over time, so for a new project it is better to check the current package version and SDK requirements before choosing a version constraint. :contentReference[oaicite:2]{index=2}
5. Importing SharedPreferences
After installing the package, import it into the Dart file.
import 'package:shared_preferences/shared_preferences.dart';
6. Getting a SharedPreferences Instance
The legacy SharedPreferences API obtains an instance asynchronously using getInstance().
final SharedPreferences prefs =
await SharedPreferences.getInstance();
This loads the preferences for the application. The current package documentation recommends SharedPreferencesAsync or SharedPreferencesWithCache for new code instead of the legacy API. :contentReference[oaicite:3]{index=3}
7. Saving String Data
Use setString() to store a string value.
final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', 'Manish');
Reading String Data
final prefs = await SharedPreferences.getInstance();
String? username = prefs.getString('username');
print(username);
If the key does not exist, the getter returns null.
8. Saving Integer Data
Use setInt() to store an integer.
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('age', 25);
Reading Integer Data
final prefs = await SharedPreferences.getInstance();
int? age = prefs.getInt('age');
print(age);
9. Saving Boolean Data
Boolean values are commonly used for flags such as login status or onboarding completion.
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLoggedIn', true);
Reading Boolean Data
final prefs = await SharedPreferences.getInstance();
bool? isLoggedIn = prefs.getBool('isLoggedIn');
print(isLoggedIn);
10. Saving Double Data
Use setDouble() to store a decimal number.
final prefs = await SharedPreferences.getInstance();
await prefs.setDouble('price', 199.99);
Reading Double Data
final prefs = await SharedPreferences.getInstance();
double? price = prefs.getDouble('price');
print(price);
11. Saving a List of Strings
SharedPreferences also supports List.
final prefs = await SharedPreferences.getInstance();
await prefs.setStringList(
'categories',
['Flutter', 'Dart', 'Firebase'],
);
Reading String List
final prefs = await SharedPreferences.getInstance();
List? categories =
prefs.getStringList('categories');
print(categories);
12. Supported Data Types
| Data Type | Save Method | Read Method |
|---|
| String | setString() | getString() |
| int | setInt() | getInt() |
| double | setDouble() | getDouble() |
| bool | setBool() | getBool() |
| List | setStringList() | getStringList() |
These are the simple data types supported by the package. :contentReference[oaicite:4]{index=4}
13. Complete Save and Read Example
import 'package:shared_preferences/shared_preferences.dart';
Future saveUserData() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', 'Manish');
await prefs.setInt('age', 25);
await prefs.setBool('isLoggedIn', true);
await prefs.setDouble('score', 95.5);
}
Future readUserData() async {
final prefs = await SharedPreferences.getInstance();
final username = prefs.getString('username');
final age = prefs.getInt('age');
final isLoggedIn = prefs.getBool('isLoggedIn');
final score = prefs.getDouble('score');
print(username);
print(age);
print(isLoggedIn);
print(score);
}
14. Updating Stored Data
Saving a value using the same key updates the existing value.
final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', 'Manish');
await prefs.setString('username', 'Rahul');
final username = prefs.getString('username');
print(username);
The value associated with username is now Rahul.
15. Removing a Specific Value
Use the remove() method to delete a specific key and its stored value.
final prefs = await SharedPreferences.getInstance();
await prefs.remove('username');
Checking After Removal
final username = prefs.getString('username');
print(username);
The result will normally be null if the key no longer exists.
16. Checking Whether a Key Exists
The containsKey() method checks whether a particular key exists.
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey('username')) {
print('Username exists');
} else {
print('Username does not exist');
}
17. Clearing Preferences
The clear() method removes the preferences stored through the API.
final prefs = await SharedPreferences.getInstance();
await prefs.clear();
Use clear() carefully because it is much broader than removing one specific key.
18. SharedPreferences for Login Status
One common use case is remembering whether the user has logged in.
Future saveLoginStatus() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLoggedIn', true);
}
Checking Login Status
Future checkLoginStatus() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool('isLoggedIn') ?? false;
}
19. Login and Logout Example
import 'package:shared_preferences/shared_preferences.dart';
Future login() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLoggedIn', true);
}
Future logout() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLoggedIn', false);
}
Future isUserLoggedIn() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool('isLoggedIn') ?? false;
}
20. SharedPreferences for Onboarding
SharedPreferences can remember whether a user has already completed an onboarding screen.
Future completeOnboarding() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('onboardingCompleted', true);
}
Checking Onboarding Status
Future isOnboardingCompleted() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool('onboardingCompleted') ?? false;
}
21. SharedPreferences for Theme Mode
An application can store whether the user selected light mode or dark mode.
Future saveDarkMode(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('darkMode', value);
}
Reading Theme Preference
Future getDarkMode() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool('darkMode') ?? false;
}
22. SharedPreferences for Language Selection
Language preferences can be stored using a string.
Future saveLanguage(String language) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('language', language);
}
Reading Language
Future getLanguage() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('language') ?? 'English';
}
23. Complete Flutter UI Example
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SharedPreferences Demo',
home: const PreferencesPage(),
);
}
}
class PreferencesPage extends StatefulWidget {
const PreferencesPage({super.key});
@override
State createState() => _PreferencesPageState();
}
class _PreferencesPageState extends State {
String username = '';
@override
void initState() {
super.initState();
loadUsername();
}
Future loadUsername() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
username = prefs.getString('username') ?? 'Guest';
});
}
Future saveUsername() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', 'Manish');
await loadUsername();
}
Future removeUsername() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('username');
await loadUsername();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SharedPreferences'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Username: $username',
style: const TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: saveUsername,
child: const Text('Save Username'),
),
ElevatedButton(
onPressed: removeUsername,
child: const Text('Remove Username'),
),
],
),
),
);
}
}
24. Async Nature of SharedPreferences
Accessing the legacy SharedPreferences instance is asynchronous because the preferences need to be initialized from platform storage.
final prefs = await SharedPreferences.getInstance();
Methods such as setString(), setInt(), and setBool() return Future in the legacy API, so they can be awaited.
25. SharedPreferences vs Database
SharedPreferences is designed for simple key-value data. It is not a replacement for a relational or document database.
| Feature | SharedPreferences | Database |
|---|
| Data Structure | Simple key-value pairs. | Structured and potentially complex data. |
| Best For | Settings and preferences. | Large or relational application data. |
| Queries | Very limited. | Supports database queries. |
| Relationships | Not designed for relationships. | Can support relationships depending on database. |
| Typical Data | Theme, language, flags, simple settings. | Users, products, orders, messages, transactions. |
26. What Should Not Be Stored?
SharedPreferences is intended for simple preference data and should not be treated as a secure database or a general-purpose database.
- Passwords.
- Authentication secrets.
- Private encryption keys.
- Highly sensitive information.
- Large amounts of application data.
- Complex relational data.
- Critical data that requires transactional database guarantees.
The package documentation specifically cautions that writes are not guaranteed to have been persisted to disk after returning, so it should not be used for critical data. :contentReference[oaicite:5]{index=5}
27. SharedPreferences and JSON
SharedPreferences does not directly provide a general-purpose object storage mechanism. If complex data needs to be represented as JSON, it can be converted to a string before storing it.
Example
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
Future saveUser() async {
final prefs = await SharedPreferences.getInstance();
final user = {
'name': 'Manish',
'age': 25,
};
final jsonString = jsonEncode(user);
await prefs.setString('user', jsonString);
}
Reading JSON
Future readUser() async {
final prefs = await SharedPreferences.getInstance();
final jsonString = prefs.getString('user');
if (jsonString != null) {
final user = jsonDecode(jsonString);
print(user['name']);
print(user['age']);
}
}
For complex or large application data, a dedicated database or appropriate storage solution is generally more suitable.
28. SharedPreferencesWithCache
The current shared_preferences package provides SharedPreferencesWithCache, which uses a local cache while providing asynchronous initialization. It can be useful when an application wants cached access after initialization. :contentReference[oaicite:6]{index=6}
Basic Example
final prefs = await SharedPreferencesWithCache.create(
cacheOptions: const SharedPreferencesWithCacheOptions(),
);
await prefs.setBool('isLoggedIn', true);
final isLoggedIn = prefs.getBool('isLoggedIn');
29. SharedPreferencesAsync
SharedPreferencesAsync is another newer API provided by the package. It provides asynchronous access to preference storage without relying on the same local cache model as the legacy API.
Basic Example
final prefs = SharedPreferencesAsync();
await prefs.setBool('isLoggedIn', true);
final isLoggedIn =
await prefs.getBool('isLoggedIn');
The current package documentation recommends considering SharedPreferencesAsync or SharedPreferencesWithCache for new code rather than the legacy SharedPreferences API. :contentReference[oaicite:7]{index=7}
30. SharedPreferences APIs Comparison
| API | Description | Recommendation |
|---|
| SharedPreferences | Legacy API using a local cache after initialization. | Useful for existing applications; consider migration for new code. |
| SharedPreferencesAsync | Asynchronous preference access. | Recommended option to consider for new code. |
| SharedPreferencesWithCache | Preference access using a managed cache. | Recommended option to consider when caching is appropriate. |
The package introduced the newer APIs in version 2.3.0 and documents the original SharedPreferences API as legacy. :contentReference[oaicite:8]{index=8}
31. Cache Considerations
The legacy SharedPreferences API and SharedPreferencesWithCache use a local cache. When multiple isolates or external processes modify the same preference storage, cached values can become stale unless they are refreshed appropriately. :contentReference[oaicite:9]{index=9}
32. Reloading Preferences
Existing applications using the legacy API may use reload() when they need to refresh cached values from the platform storage.
final prefs = await SharedPreferences.getInstance();
await prefs.reload();
final value = prefs.getString('username');
33. Key Naming Best Practices
Use clear and consistent names for preference keys.
Good Examples
isLoggedIn
username
darkMode
selectedLanguage
onboardingCompleted
notificationEnabled
Avoid Unclear Keys
x
data1
temp
abc
Clear key names make the code easier to understand and maintain.
34. Creating a Preferences Service
Instead of accessing SharedPreferences throughout the entire application, a dedicated service can centralize preference operations.
import 'package:shared_preferences/shared_preferences.dart';
class PreferencesService {
Future saveUsername(String username) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('username', username);
}
Future getUsername() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('username');
}
Future removeUsername() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('username');
}
}
35. Using the Preferences Service
final preferences = PreferencesService();
await preferences.saveUsername('Manish');
final username =
await preferences.getUsername();
print(username);
This approach keeps storage-related code organized and makes the application easier to maintain.
36. Practical Login Flow
Login Screen
|
v
User Enters Credentials
|
v
Authentication Successful
|
v
Save isLoggedIn = true
|
v
Open Home Screen
|
v
Application Restart
|
v
Read isLoggedIn
|
+---- true ----> Home Screen
|
+---- false ---> Login Screen
37. Practical Onboarding Flow
Application Starts
|
v
Read onboardingCompleted
|
+---- false ----> Show Onboarding
| |
| v
| Save true
| |
+-----------------------+
|
+---- true -----> Show Home Screen
38. Best Practices
- Use SharedPreferences for small and simple key-value data.
- Use meaningful key names.
- Keep preference access centralized when the application becomes large.
- Use
await for asynchronous operations.
- Provide default values when a key may not exist.
- Do not store passwords or highly sensitive secrets in SharedPreferences.
- Do not use SharedPreferences as a replacement for a database.
- Review the current package API when starting a new project.
- For new code, consider
SharedPreferencesAsync or SharedPreferencesWithCache.
- Test preference behavior when the application is restarted.
39. Common Mistakes
| Mistake | Problem | Better Approach |
|---|
| Storing passwords | SharedPreferences is not designed as secure secret storage. | Use an appropriate secure-storage solution. |
| Storing large data | SharedPreferences is designed for simple preferences. | Use a database or suitable storage solution. |
| Using unclear keys | Makes maintenance difficult. | Use descriptive key names. |
| Forgetting await | Can cause asynchronous operations to be handled incorrectly. | Await asynchronous methods. |
| Using clear() unnecessarily | Can remove more preferences than intended. | Use remove() for a specific key. |
| Ignoring cache behavior | Values can become stale in certain multi-isolate or external-update scenarios. | Choose the appropriate current API and refresh strategy. |
40. Interview Questions
Q1. What is SharedPreferences in Flutter?
SharedPreferences is a plugin for storing and retrieving simple key-value data persistently.
Q2. What data types can SharedPreferences store?
It supports int, double, bool, String, and List. :contentReference[oaicite:10]{index=10}
Q3. How do you install SharedPreferences?
flutter pub add shared_preferences
Q4. How do you get a SharedPreferences instance?
final prefs = await SharedPreferences.getInstance();
Q5. How do you store a string?
await prefs.setString('username', 'Manish');
Q6. How do you retrieve a string?
final username = prefs.getString('username');
Q7. How do you remove a value?
await prefs.remove('username');
Q8. How do you clear stored preferences?
await prefs.clear();
Q9. Can SharedPreferences store objects directly?
No. The standard supported values are simple primitive types and List. Complex objects need to be transformed into a supported representation, such as a JSON string, or stored using a more appropriate database or storage solution. :contentReference[oaicite:11]{index=11}
Q10. Is SharedPreferences suitable for passwords?
No. SharedPreferences is intended for simple preferences and should not be treated as secure storage for sensitive secrets.
Q11. What is SharedPreferencesAsync?
SharedPreferencesAsync is a newer API in the shared_preferences package that provides asynchronous access to preference storage.
Q12. Which API should new applications consider?
The current package documentation recommends considering SharedPreferencesAsync or SharedPreferencesWithCache for new code instead of the legacy SharedPreferences API. :contentReference[oaicite:12]{index=12}
41. Summary
- SharedPreferences is used for simple persistent key-value storage.
- The package can store strings, integers, doubles, booleans, and string lists.
- The package can be added using
flutter pub add shared_preferences.
- The legacy API uses
SharedPreferences.getInstance().
setString(), setInt(), setDouble(), setBool(), and setStringList() save data.
getString(), getInt(), getDouble(), getBool(), and getStringList() retrieve data.
remove() deletes a specific preference.
clear() removes stored preferences.
- SharedPreferences is useful for settings, flags, onboarding status, and simple preferences.
- It should not be used as a secure storage mechanism for passwords or sensitive secrets.
- It should not replace a database for large or complex application data.
- The current package provides
SharedPreferencesAsync and SharedPreferencesWithCache for newer usage patterns.
Learn Flutter
JustAcademy Flutter Training Course
Register for Flutter Course Demo