If you have a relatively small collection of key-values that you’d liketo save, you can use theshared_preferences plugin.

Normally you would have to write native platform integrations for storingdata on both platforms. Fortunately, theshared_preferencesplugin can be used to persist key-value data on disk. The shared preferencesplugin wraps NSUserDefaults on iOS and SharedPreferences on Android,providing a persistent store for simple data.

Directions

  • Add the dependency
  • Save Data
  • Read Data
  • Remove Data

1. Add the dependency

Before starting, you need to add theshared_preferencesplugin to the pubspec.yaml file:

  1. dependencies:
  2. flutter:
  3. sdk: flutter
  4. shared_preferences: "<newest version>"

2. Save data

To persist data, use the setter methods provided by theSharedPreferences class. Setter methods are available for various primitivetypes, such as setInt, setBool, and setString.

Setter methods do two things: First, synchronously update the key-value pairin-memory. Then, persist the data to disk.

  1. // obtain shared preferences
  2. final prefs = await SharedPreferences.getInstance();
  3. // set value
  4. prefs.setInt('counter', counter);

3. Read data

To read data, use the appropriate getter method provided by theSharedPreferences class. For each setter there is a corresponding getter.For example, you can use the getInt, getBool, and getString methods.

  1. final prefs = await SharedPreferences.getInstance();
  2. // Try reading data from the counter key. If it does not exist, return 0.
  3. final counter = prefs.getInt('counter') ?? 0;

4. Remove data

To delete data, use the remove method.

  1. final prefs = await SharedPreferences.getInstance();
  2. prefs.remove('counter');

Supported types

While it is easy and convenient to use key-value storage, it has limitations:

  • Only primitive types can be used: int, double, bool, string andstringList
  • It’s not designed to store a lot of data.For more information about Shared Preferences on Android, seeShared preferencesdocumentationon the Android developers website.

Testing support

It can be a good idea to test code that persists data usingshared_preferences. To do so, you’ll need to mock out theMethodChannel used by the shared_preferences library.

You can populate SharedPreferences with initial values in your testsby running the following code in a setupAll method in your test files:

  1. const MethodChannel('plugins.flutter.io/shared_preferences')
  2. .setMockMethodCallHandler((MethodCall methodCall) async {
  3. if (methodCall.method == 'getAll') {
  4. return <String, dynamic>{}; // set initial values here if desired
  5. }
  6. return null;
  7. });

Example

  1. import 'package:flutter/material.dart';
  2. import 'package:shared_preferences/shared_preferences.dart';
  3. void main() => runApp(MyApp());
  4. class MyApp extends StatelessWidget {
  5. // This widget is the root of the application.
  6. @override
  7. Widget build(BuildContext context) {
  8. return MaterialApp(
  9. title: 'Shared preferences demo',
  10. theme: ThemeData(
  11. primarySwatch: Colors.blue,
  12. ),
  13. home: MyHomePage(title: 'Shared preferences demo'),
  14. );
  15. }
  16. }
  17. class MyHomePage extends StatefulWidget {
  18. MyHomePage({Key key, this.title}) : super(key: key);
  19. final String title;
  20. @override
  21. _MyHomePageState createState() => _MyHomePageState();
  22. }
  23. class _MyHomePageState extends State<MyHomePage> {
  24. int _counter = 0;
  25. @override
  26. void initState() {
  27. super.initState();
  28. _loadCounter();
  29. }
  30. //Loading counter value on start
  31. _loadCounter() async {
  32. SharedPreferences prefs = await SharedPreferences.getInstance();
  33. setState(() {
  34. _counter = (prefs.getInt('counter') ?? 0);
  35. });
  36. }
  37. //Incrementing counter after click
  38. _incrementCounter() async {
  39. SharedPreferences prefs = await SharedPreferences.getInstance();
  40. setState(() {
  41. _counter = (prefs.getInt('counter') ?? 0) + 1;
  42. prefs.setInt('counter', _counter);
  43. });
  44. }
  45. @override
  46. Widget build(BuildContext context) {
  47. return Scaffold(
  48. appBar: AppBar(
  49. title: Text(widget.title),
  50. ),
  51. body: Center(
  52. child: Column(
  53. mainAxisAlignment: MainAxisAlignment.center,
  54. children: <Widget>[
  55. Text(
  56. 'You have pushed the button this many times:',
  57. ),
  58. Text(
  59. '$_counter',
  60. style: Theme.of(context).textTheme.display1,
  61. ),
  62. ],
  63. ),
  64. ),
  65. floatingActionButton: FloatingActionButton(
  66. onPressed: _incrementCounter,
  67. tooltip: 'Increment',
  68. child: Icon(Icons.add),
  69. ), // This trailing comma makes auto-formatting nicer for build methods.
  70. );
  71. }
  72. }