How to Save and Load Data in Flutter Using SharedPreferences
Tags: flutter, dart, data, sharedpreferences
Published: 2024-07-17 02:19:30

Managing data in mobile applications is crucial for providing a seamless user experience. One of the simplest ways to store data in Flutter is by using the shared_preferences package. This package allows you to save and retrieve data in a key-value pair format, making it perfect for storing simple data like user preferences, settings, and basic app state information.

In this blog, we’ll cover:

1. Setting up your Flutter project with shared_preferences
2. Saving and loading numbers
3. Saving and loading strings
4. Saving and loading JSON data
5. A real-life use case example

## 1. Setting Up Your Flutter Project with SharedPreferences

### Step 1: Add Dependencies

First, add the shared_preferences package to your project. Open pubspec.yaml and add the dependency:

```
dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.0.8
```
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';`

## 2. Saving and Loading Numbers

### Saving a Number

To save a number, you can use the `setInt` method:

```
Future<void> saveNumber(int number) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setInt('my_number', number);
}
```

### Loading a Number

To load a number, use the `getInt` method:

```
Future<int?> loadNumber() async {
  final prefs = await SharedPreferences.getInstance();
  return prefs.getInt('my_number');
}
```

## 3. Saving and Loading Strings

### Saving a String

To save a string, use the `setString` method:

```
Future<void> saveString(String value) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('my_string', value);
}
```

### Loading a String

To load a string, use the `getString` method:

```
Future<String?> loadString() async {
  final prefs = await SharedPreferences.getInstance();
  return prefs.getString('my_string');
}
```

## 4. Saving and Loading JSON Data

### Saving JSON Data

To save JSON data, first convert the data to a string:

```
import 'dart:convert';

Future<void> saveJson(Map<String, dynamic> data) async {
  final prefs = await SharedPreferences.getInstance();
  String jsonString = jsonEncode(data);
  await prefs.setString('my_json', jsonString);
}
```

### Loading JSON Data

To load JSON data, convert the string back to a map:

```
Future<Map<String, dynamic>?> loadJson() async {
  final prefs = await SharedPreferences.getInstance();
  String? jsonString = prefs.getString('my_json');
  if (jsonString != null) {
    return jsonDecode(jsonString);
  }
  return null;
}
```

## 5. Real-Life Use Case Example: User Profile Management

Imagine you have an app where users can set their profile information, including their age (number), name (string), and preferences (JSON). Here’s how you can save and load this information using _shared_preferences_.

### Step 1: Save User Profile

```
Future<void> saveUserProfile(int age, String name, Map<String, dynamic> preferences) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setInt('user_age', age);
  await prefs.setString('user_name', name);
  String preferencesString = jsonEncode(preferences);
  await prefs.setString('user_preferences', preferencesString);
}
```

### Step 2: Load User Profile

```
Future<Map<String, dynamic>> loadUserProfile() async {
  final prefs = await SharedPreferences.getInstance();
  
  int? age = prefs.getInt('user_age');
  String? name = prefs.getString('user_name');
  String? preferencesString = prefs.getString('user_preferences');
  Map<String, dynamic>? preferences = preferencesString != null ? jsonDecode(preferencesString) : null;
  
  return {
    'age': age,
    'name': name,
    'preferences': preferences,
  };
}
```

### Step 3: Example Usage in a Flutter App

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UserProfilePage(),
    );
  }
}

class UserProfilePage extends StatefulWidget {
  @override
  _UserProfilePageState createState() => _UserProfilePageState();
}

class _UserProfilePageState extends State<UserProfilePage> {
  int _age = 0;
  String _name = '';
  Map<String, dynamic> _preferences = {};

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

  Future<void> _saveUserProfile() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt('user_age', _age);
    await prefs.setString('user_name', _name);
    String preferencesString = jsonEncode(_preferences);
    await prefs.setString('user_preferences', preferencesString);
  }

  Future<void> _loadUserProfile() async {
    final prefs = await SharedPreferences.getInstance();
    
    setState(() {
      _age = prefs.getInt('user_age') ?? 0;
      _name = prefs.getString('user_name') ?? '';
      String? preferencesString = prefs.getString('user_preferences');
      _preferences = preferencesString != null ? jsonDecode(preferencesString) : {};
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('User Profile'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              decoration: InputDecoration(labelText: 'Name'),
              onChanged: (value) {
                setState(() {
                  _name = value;
                });
              },
              controller: TextEditingController(text: _name),
            ),
            TextField(
              decoration: InputDecoration(labelText: 'Age'),
              keyboardType: TextInputType.number,
              onChanged: (value) {
                setState(() {
                  _age = int.parse(value);
                });
              },
              controller: TextEditingController(text: _age.toString()),
            ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _preferences['dark_mode'] = !_preferences.containsKey('dark_mode') ? true : !_preferences['dark_mode'];
                });
              },
              child: Text('Toggle Dark Mode'),
            ),
            ElevatedButton(
              onPressed: _saveUserProfile,
              child: Text('Save Profile'),
            ),
            ElevatedButton(
              onPressed: _loadUserProfile,
              child: Text('Load Profile'),
            ),
            SizedBox(height: 20),
            Text('Name: $_name'),
            Text('Age: $_age'),
            Text('Preferences: ${_preferences.toString()}'),
          ],
        ),
      ),
    );
  }
}
```

### Conclusion

Using shared_preferences in Flutter is an effective way to store and retrieve simple data like numbers, strings, and JSON objects. This guide has shown you how to set up and use shared_preferences for different data types and provided a real-life example of managing user profiles. By integrating shared_preferences into your Flutter app, you can enhance user experience by maintaining state and preferences across sessions.

Further Readings:
[package info](https://pub.dev/packages/shared_preferences)
[docs](https://docs.flutter.dev/cookbook/persistence/key-value)
[youtube tutorial](https://www.youtube.com/watch?v=aIirO4sId60)