Skip to main content
Flutter Basics – Complete Beginner to Advanced Guide
CHAPTER 20 Beginner

Local Storage and Shared Preferences

Updated: May 16, 2026
25 min read

# CHAPTER 20

Local Storage and Shared Preferences

1. Introduction

When a user toggles "Dark Mode" in your app, they expect the app to still be in Dark Mode when they open it the next day. However, standard variables (like bool isDark = true) are stored in RAM. When the app is closed, RAM is wiped clean, and the variable resets. To remember settings permanently, you must write data directly to the phone's physical hard drive. In this chapter, we will master Local Storage and Shared Preferences. We will install the industry-standard package to easily read, write, and delete small pieces of data (like high scores, login tokens, and user preferences) so your app remembers who the user is.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Install and initialize the sharedpreferences package.
  • Write Strings, Integers, and Booleans to the device's local storage.
  • Read stored data asynchronously on app startup.
  • Delete or clear stored preferences.
  • Understand the limitations of Shared Preferences vs a true database.

3. What are Shared Preferences?

shared
preferences is an official Flutter package that wraps the native storage systems of the operating system (Android SharedPreferences and iOS NSUserDefaults). It stores data in simple Key-Value pairs.
  • Key: "username" -> Value: "Alice"
  • Key: "highscore" -> Value: 450

*Important: It is designed for SMALL amounts of data (under a few megabytes). Do not try to store 10,000 chat messages here.*

4. Installation and Setup

  1. 1. Add the package to your pubspec.yaml:
shared
preferences: ^2.2.0
  1. 2. Import it in your Dart file:
import 'package:sharedpreferences/sharedpreferences.dart';

5. Saving Data (Writing)

Writing to the hard drive is a physical disk operation, which means it takes time. Therefore, we must use async and await!
dart
12345678910
// Function to save a high score
Future<void> saveHighScore(int score) async {
  // 1. Get the physical disk instance
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  
  // 2. Save the data! (Requires a Key and the Value)
  await prefs.setInt(&#039;high_score_key', score);
  
  print("Score saved to hard drive!");
}

*(You can also use .setString, .setBool, and .setDouble depending on your data type).*

6. Loading Data (Reading)

When the app launches, you want to grab the saved score to display it. If the app has never been opened before, the data won't exist! You must provide a fallback value (like 0).
dart
123456789
// Function to load the high score
Future<int> loadHighScore() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  
  // Try to read the key. If it returns null, default to 0!
  int savedScore = prefs.getInt(&#039;high_score_key') ?? 0;
  
  return savedScore;
}

7. Deleting Data

When a user clicks "Log Out", you must delete their stored login token from the hard drive.
dart
123456789
Future<void> logOutUser() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  
  // Remove a specific key
  await prefs.remove(&#039;user_auth_token');
  
  // OR: Wipe the ENTIRE storage clean!
  // await prefs.clear(); 
}

8. Mini Project: The Remember Me Nameplate

Let's build a UI that asks for a name, saves it, and displays it automatically the next time the app opens.
dart
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
class ProfileScreen extends StatefulWidget {
  @override
  _ProfileScreenState createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State<ProfileScreen> {
  String savedName = "Guest";
  TextEditingController _nameController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _loadName(); // Fetch data the millisecond the screen opens!
  }

  // Read from Disk
  Future<void> _loadName() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      savedName = prefs.getString(&#039;user_name') ?? "Guest";
    });
  }

  // Write to Disk
  Future<void> _saveName() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(&#039;user_name', _nameController.text);
    _loadName(); // Reload the UI to show the new name
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text("Welcome back, $savedName!"),
          TextField(controller: _nameController),
          ElevatedButton(
            onPressed: _saveName,
            child: Text("Save My Name Permanently"),
          )
        ],
      ),
    );
  }
}

9. Common Mistakes

  • Storing Sensitive Data: sharedpreferences saves data in plain text XML files on the phone. Do NOT store raw passwords, credit card numbers, or secure encryption keys here! A rooted/jailbroken phone can easily read these files. For sensitive data, use the fluttersecurestorage package instead.

10. Best Practices

  • Define Keys as Constants: If you misspell 'username' as 'username' when trying to read the data, it will return null. Always define your keys as constants at the top of your file: const String KEYNAME = 'username'; and use prefs.getString(KEYNAME) to eliminate typo bugs.

11. Practice Exercises

  1. 1. What official Flutter package is used to save simple Key-Value pairs to the device's local hard drive?
  1. 2. Why is the await keyword mandatory when calling SharedPreferences.getInstance()?

12. MCQs with Answers

Question 1

A developer wants to save an offline catalog of 5,000 product objects including titles, descriptions, and prices. Why is sharedpreferences a poor choice for this task?

Question 2

When attempting to read a setting via prefs.getBool('isDarkMode'), what does the method return if the user has never opened the app before and the key does not exist?

13. Interview Questions

  • Q: Explain the purpose of sharedpreferences in the Flutter ecosystem. Provide three examples of data perfectly suited for this package.
  • Q: Contrast sharedpreferences with fluttersecurestorage. When is it absolutely mandatory to use the latter?
  • Q: Describe how you would utilize the initState method in a StatefulWidget to seamlessly load and display a user's saved preferences exactly when the app launches.

14. FAQs

Q: Can I save a custom Object (like a User class) into Shared Preferences? A: Not directly. You can only save strings. You must encode your User object into a JSON String using jsonEncode(), save the string, and then jsonDecode() it when you read it back.

15. Summary

In Chapter 20, we gave our application a permanent memory. We moved beyond temporary RAM variables and utilized the shared_preferences package to write data directly to the device's physical hard drive. We mastered the asynchronous workflow required for disk operations, writing data using .setString() and reading it smoothly upon app launch using .getString() combined with initState. We learned to define fallback values using ?? to prevent null errors, and established the security rules of what *not* to store in plain text.

16. Next Chapter Recommendation

Shared Preferences is excellent for small settings, but what if we need to store 10,000 offline chat messages? We need a real, queryable database. Proceed to Chapter 21: SQLite Database in Flutter.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·