Using Shared Preferences for Simple Data Storage in Flutter

In Flutter, SharedPreferences provides a straightforward way to store simple data persistently across app sessions. It’s ideal for saving user preferences, app settings, or small amounts of data that you want to retain between app launches. This article will guide you through how to use SharedPreferences effectively in your Flutter applications, complete with detailed code examples and best practices.

What is SharedPreferences?

SharedPreferences is a simple storage solution for key-value pairs. It allows you to store data types such as integers, doubles, booleans, and strings. The data is stored in a platform-specific manner: on Android, it uses the SharedPreferences class, and on iOS, it uses NSUserDefaults.

Why Use SharedPreferences?

  • Simple: Easy to implement and use for basic data storage needs.
  • Persistent: Data persists across app sessions, allowing you to maintain state.
  • Platform-Native: Utilizes native platform storage, ensuring reliability.

How to Use SharedPreferences in Flutter

Step 1: Add the shared_preferences Dependency

First, add the shared_preferences package to your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2

Run flutter pub get to install the package.

Step 2: Import the shared_preferences Package

Import the shared_preferences package in your Dart file:

import 'package:shared_preferences/shared_preferences.dart';

Step 3: Storing Data

You can store data using the SharedPreferences instance. Here’s how to store different types of data:

import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesService {
  static Future setString(String key, String value) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(key, value);
  }

  static Future setInt(String key, int value) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt(key, value);
  }

  static Future setDouble(String key, double value) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setDouble(key, value);
  }

  static Future setBoolean(String key, bool value) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool(key, value);
  }
}

Example Usage:

void saveData() async {
  await SharedPreferencesService.setString('username', 'johndoe');
  await SharedPreferencesService.setInt('age', 30);
  await SharedPreferencesService.setDouble('height', 1.75);
  await SharedPreferencesService.setBoolean('isLoggedIn', true);
}

Step 4: Retrieving Data

Retrieve data using the appropriate getter method:

import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesService {
  static Future getString(String key) async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString(key);
  }

  static Future getInt(String key) async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getInt(key);
  }

  static Future getDouble(String key) async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getDouble(key);
  }

  static Future getBoolean(String key) async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getBool(key);
  }
}

Example Usage:

void loadData() async {
  final username = await SharedPreferencesService.getString('username');
  final age = await SharedPreferencesService.getInt('age');
  final height = await SharedPreferencesService.getDouble('height');
  final isLoggedIn = await SharedPreferencesService.getBoolean('isLoggedIn');

  print('Username: $username');
  print('Age: $age');
  print('Height: $height');
  print('Is Logged In: $isLoggedIn');
}

Step 5: Removing Data

Remove data by using the remove() method:

import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesService {
  static Future remove(String key) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(key);
  }
}

Example Usage:

void removeData() async {
  await SharedPreferencesService.remove('username');
}

Step 6: Clearing All Data

You can clear all stored data using the clear() method:

import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesService {
  static Future clear() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.clear();
  }
}

Example Usage:

void clearAllData() async {
  await SharedPreferencesService.clear();
}

Complete Example: Storing and Retrieving a Theme Preference

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
  ThemeMode _themeMode = ThemeMode.system; // Default theme

  @override
  void initState() {
    super.initState();
    _loadThemePreference();
  }

  Future _loadThemePreference() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _themeMode = (prefs.getString('theme') == 'dark') ? ThemeMode.dark : ThemeMode.light;
    });
  }

  Future _saveThemePreference(ThemeMode theme) async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _themeMode = theme;
    });
    await prefs.setString('theme', theme == ThemeMode.dark ? 'dark' : 'light');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Theme Demo',
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: _themeMode,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Theme Preference Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'Current Theme: ${_themeMode.toString().split('.').last}',
                style: const TextStyle(fontSize: 20),
              ),
              ElevatedButton(
                onPressed: () {
                  _saveThemePreference(_themeMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light);
                },
                child: const Text('Toggle Theme'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

This example allows you to toggle between light and dark themes, saving the preference using SharedPreferences.

Best Practices for Using SharedPreferences

  • Use Asynchronously: Always use SharedPreferences asynchronously to avoid blocking the UI thread.
  • Handle Errors: Implement error handling to catch potential exceptions.
  • Avoid Storing Large Data: SharedPreferences is not suitable for storing large datasets.
  • Organize Keys: Use descriptive and consistent key names to manage your data effectively.

Conclusion

SharedPreferences is an excellent choice for simple data storage in Flutter, allowing you to persist user preferences and settings across app sessions. By following the guidelines and examples in this article, you can effectively use SharedPreferences to enhance your Flutter applications.