Using the shared_preferences Package for Storing Simple Key-Value Data Locally in Flutter

In Flutter development, managing data efficiently is crucial for creating robust and user-friendly applications. The shared_preferences package is a simple and effective way to store key-value pairs locally on a user’s device. This is particularly useful for persisting simple data such as user settings, preferences, or small amounts of application state between app sessions.

What is shared_preferences?

shared_preferences is a Flutter plugin that provides a persistent store for simple data. It wraps platform-specific storage (NSUserDefaults on iOS and SharedPreferences on Android), offering a consistent API across both platforms. This plugin allows you to read and write primitive data types such as integers, doubles, booleans, strings, and string lists to persistent storage.

Why Use shared_preferences?

  • Simple Data Persistence: Easily store and retrieve small amounts of data.
  • Cross-Platform Compatibility: Works seamlessly on both iOS and Android.
  • Asynchronous Operations: Provides asynchronous APIs to avoid blocking the UI thread.
  • Easy to Use: Simple API for storing and retrieving key-value pairs.

How to Use shared_preferences in Flutter

To use shared_preferences in your Flutter project, follow these steps:

Step 1: Add the Dependency

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

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2 # Use the latest version

Then, run flutter pub get in your terminal to install the package.

Step 2: Import the Package

Import the shared_preferences package into your Dart file:

import 'package:shared_preferences/shared_preferences.dart';

Step 3: Store Data

To store data, you need to get an instance of SharedPreferences and then use the appropriate setter method based on the data type you want to store:

import 'package:shared_preferences/shared_preferences.dart';

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

Step 4: Retrieve Data

To retrieve data, use the getter methods provided by SharedPreferences, ensuring you handle the possibility of null values:

import 'package:shared_preferences/shared_preferences.dart';

Future retrieveData() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  final int? counter = prefs.getInt('counter');
  final bool? isLoggedIn = prefs.getBool('isLoggedIn');
  final String? userName = prefs.getString('userName');
  final double? piValue = prefs.getDouble('piValue');
  final List? favoriteColors = prefs.getStringList('favoriteColors');

  print('Counter: $counter');
  print('Is Logged In: $isLoggedIn');
  print('User Name: $userName');
  print('Pi Value: $piValue');
  print('Favorite Colors: $favoriteColors');
}

Step 5: Example Usage in a Flutter App

Here’s a simple Flutter app demonstrating how to use shared_preferences to persist a counter value:

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',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  int _counter = 0;

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

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

  // Increment the counter and save it to SharedPreferences
  Future _incrementCounter() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      _counter++;
    });
    await 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(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Explanation of the Code:

  • The _loadCounter method retrieves the counter value from SharedPreferences when the app starts.
  • The _incrementCounter method increments the counter, updates the UI, and saves the new value to SharedPreferences.
  • The initState method calls _loadCounter to ensure that the counter value is loaded when the widget is initialized.

Important Considerations

  • Error Handling: Always handle potential exceptions, especially when dealing with asynchronous operations.
  • Data Security: shared_preferences is not suitable for storing sensitive data. For sensitive information, consider using secure storage options like flutter_secure_storage.
  • Data Size: shared_preferences is designed for small amounts of data. For larger datasets, use local databases like SQLite (via the sqflite package) or NoSQL databases like Hive.

Conclusion

The shared_preferences package is a convenient way to store and retrieve simple key-value data locally in Flutter. It’s ideal for persisting user preferences and basic app state. By following the steps outlined in this guide, you can effectively integrate shared_preferences into your Flutter applications, enhancing the user experience by preserving data between sessions.