Storing Data in SharedPreferences in Flutter

In Flutter development, persisting data locally is crucial for enhancing the user experience. SharedPreferences is a simple and widely used mechanism for storing key-value pairs persistently across application sessions. It’s ideal for storing small amounts of primitive data such as user preferences, app settings, or simple state information. This article will guide you through storing and retrieving data using SharedPreferences in Flutter.

What is SharedPreferences in Flutter?

SharedPreferences is a Flutter plugin that provides a persistent store for simple data. It’s similar to NSUserDefaults on iOS and SharedPreferences on Android, allowing you to store primitive data types like integers, doubles, booleans, and strings in key-value pairs.

Why Use SharedPreferences?

  • Simplicity: Easy to implement and use for small-scale data persistence.
  • Persistent Storage: Data is stored persistently across app sessions.
  • Cross-Platform: Works seamlessly on both iOS and Android.

How to Use SharedPreferences in Flutter

Follow these steps to implement SharedPreferences in your Flutter app:

Step 1: Add the SharedPreferences Dependency

Add the shared_preferences plugin 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 Package

Import the shared_preferences package in your Dart file:

import 'package:shared_preferences/shared_preferences.dart';

Step 3: Storing Data

You can store different data types using the respective setter methods provided by the SharedPreferences class. Here’s how you can store data:

import 'package:shared_preferences/shared_preferences.dart';

Future storeData() async {
  final prefs = await SharedPreferences.getInstance();
  
  prefs.setInt('counter', 42);
  prefs.setDouble('pi', 3.14159);
  prefs.setBool('isLoggedIn', true);
  prefs.setString('username', 'FlutterDev');
  prefs.setStringList('favoriteColors', ['blue', 'green', 'red']);
}

Explanation:

  • SharedPreferences.getInstance() gets the instance of SharedPreferences asynchronously.
  • setInt, setDouble, setBool, and setString are methods used to store corresponding data types with a given key.
  • setStringList is used to store a list of strings.

Step 4: Retrieving Data

To retrieve data, use the getter methods that correspond to the data type you want to retrieve. If the key does not exist, the getter methods return a default value (e.g., null for String).

import 'package:shared_preferences/shared_preferences.dart';

Future retrieveData() async {
  final prefs = await SharedPreferences.getInstance();

  final int? counter = prefs.getInt('counter');
  final double? pi = prefs.getDouble('pi');
  final bool? isLoggedIn = prefs.getBool('isLoggedIn');
  final String? username = prefs.getString('username');
  final List? favoriteColors = prefs.getStringList('favoriteColors');

  print('Counter: $counter');
  print('Pi: $pi');
  print('IsLoggedIn: $isLoggedIn');
  print('Username: $username');
  print('Favorite Colors: $favoriteColors');
}

Explanation:

  • getInt, getDouble, getBool, and getString are methods used to retrieve data by key.
  • Type annotations (e.g., int?) indicate nullable types, as the values might be null if the key does not exist.

Step 5: Removing Data

You can remove a key-value pair from SharedPreferences using the remove method or clear all data using the clear method.

import 'package:shared_preferences/shared_preferences.dart';

Future removeData() async {
  final prefs = await SharedPreferences.getInstance();

  // Remove a single key-value pair
  await prefs.remove('username');

  // Clear all data
  // await prefs.clear();
}

Complete Example

Here is a complete example demonstrating how to use SharedPreferences in a simple Flutter app:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SharedPreferences Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  int _counter = 0;

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

  // Load counter value on start
  _loadCounter() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter = (prefs.getInt('counter') ?? 0);
    });
  }

  // Incrementing counter after click
  _incrementCounter() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter = (_counter + 1);
      prefs.setInt('counter', _counter);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SharedPreferences Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Counter Value:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

In this example:

  • The counter value is loaded from SharedPreferences in initState.
  • The counter is incremented when the floating action button is pressed.
  • The new counter value is stored in SharedPreferences.

Best Practices

  • Use Asynchronously: Always use async and await when interacting with SharedPreferences to avoid blocking the UI thread.
  • Error Handling: Implement proper error handling when accessing SharedPreferences.
  • Simple Data: SharedPreferences is best suited for simple data types and small datasets. For complex data, consider using other storage options like SQLite or Hive.
  • Key Naming: Use descriptive and consistent key names to avoid conflicts and improve readability.

Conclusion

SharedPreferences is a straightforward and effective way to store small amounts of persistent data in Flutter applications. By following the steps outlined in this article, you can easily implement data persistence for user preferences, app settings, and other simple state information, enhancing the user experience of your Flutter apps.