Best Flutter SharedPreferences Packages

In both Android and iOS, we are natively provided with a way to store a small collection of Key-Value pairs. In iOS we use NSUserDefaults while in Android we have the SharedPreference. Each of these APIs point to a file containing key-balue pairs. They then provide simple methods that allow for reading and writing them.

You may already know that Flutter does support app creation for both platforms. Thus it has to cater for completely different frameworks APIs and has to provide us classes that are compatible with both.

In this piece we want to see some of the plugins or packages that allow us save key/value pairs in Flutter. And obviously those plugins have to cater for both frameworks in a single codebase.

(a). shared_preferences

This is the plugin provided as a standard library for working with shared preferences.

It works by wrapping NSUserDefaults(iOS) and SharedPreferences(Android) resulting in a single API that allows asynchronous data persistence. It should be noted that you shouldn’t use SharedPreference as a technique for persisting critical or highly important data. This is because in both platforms there is no guarantee that data is going to be persisted on the disk.

If you want to store critical data locally then store them in SQLite database.

Installation

To install shared_preferences, go to your pubspec.yaml and add depend on it:

dependencies:
  shared_preferences: ^0.5.4+5

Then install it:

$ flutter pub get

Usage

To use shared_preferences start by importing:

import 'package:shared_preferences/shared_preferences.dart';

Here is a full example

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

void main() {
  runApp(MaterialApp(
    home: Scaffold(
      body: Center(
      child: RaisedButton(
        onPressed: _incrementCounter,
        child: Text('Increment Counter'),
        ),
      ),
    ),
  ));
}

_incrementCounter() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  int counter = (prefs.getInt('counter') ?? 0) + 1;
  print('Pressed $counter times.');
  await prefs.setInt('counter', counter);
}

Read more here.

(b). pref_dessert

This is a library that allows you to also persist objects as shared preferences and not just simple data types.

Installation

Go to your pubspec.yaml and add the following:

dependencies:
  pref_dessert: ^0.4.0+1

Then install it:

dependencies:
  pref_dessert: ^0.4.0+1

Example

Let’s say you want to persist Person object as shared preference.

In that case we assume you have a Person class:

class Person {
  String name;
  int age;

  Person(this.name, this.age);
}

You then need to extend DesSer<T> class where T is the class whose object you intend to persist:

class PersonDesSer extends DesSer<Person>{
  @override
  Person deserialize(String s) {
    var split = s.split(",");
    return new Person(split[0], int.parse(split[1]));
  }

  @override
  String serialize(Person t) {
    return "${t.name},${t.age}";
  }

}

In the above it has been serialized into CSV format.

Well you can also serialize into JSON using the convert package:

import 'dart:convert';

class JsonPersonDesSer extends DesSer<Person>{
  @override
  Person deserialize(String s) {
    var map = json.decode(s);
    return new Person(map['name'] as String, map['age'] as int);
  }

  @override
  String serialize(Person t) {
    var map = {"name":t.name, "age":t.age};
    return json.encode(map);
  }

}

The last step is to instantiate either class and pass the instance to the FuturePreferencesRepository<T>:

var repo = new FuturePreferencesRepository<Person>(new PersonDesSer());
repo.save(new Person("FooBar", 42));
var list = repo.findAll();

(c). rx_shared_preferences

This is a reactive Shared preference for Flutter based on RxDart.

Installation

In your pubspec.yaml:

dependencies:
  rx_shared_preferences: ^1.0.3+2

Then install it:

$ flutter pub get

Usage

  1. First import it:
    import 'package:rx_shared_preferences/rx_shared_preferences.dart';
    import 'package:shared_preferences/shared_preferences.dart';
  2. Then Wrap your SharedPreferences in a RxSharedPreferences.

final rxPrefs = RxSharedPreferences(
  await SharedPreferences.getInstance()
);

or:

final rxPrefs = RxSharedPreferences(
  SharedPreferences.getInstance()
);

You can even add a Logger:

final rxPrefs = RxSharedPreferences(
  SharedPreferences.getInstance(),
  const DefaultLogger(),
);

3. Oberserve and Transform the Observable

You start by Obersving or Listening:

// Observer
rxPrefs.getStringListObservable('KEY_LIST').listen(print); // [*]

Broadcast Operators like share,shareValue, publish, publishValue allow you to listen to the Observer multiple times:

// Broadcast stream
rxPrefs.getStringListObservable('KEY_LIST').share();
rxPrefs.getStringListObservable('KEY_LIST').shareValue();

Then you can transform various operators like map,flatmap etc:

// Transform stream
rxPrefs.getIntObservable('KEY_INT')
  .map((i) => /* Do something cool */)
  .where((i) => /* Filtering */)
  ...

// must **use same rxPrefs** instance when set value and select stream
rxPrefs.setStringList('KEY_LIST', ['Cool']); // [*] will print ['Cool']

4. Save/Retrieve Data

Here are teh several methods you can use to manipulate data:

Future<bool> containsKey(String key);
Future<dynamic> get(String key);
Future<bool> getBool(String key);
Future<double> getDouble(String key);
Future<int> getInt(String key);
Future<Set<String>> getKeys();
Future<String> getString(String key);
Future<List<String>> getStringList(String key);

Future<bool> clear();
Future<void> reload();
Future<bool> commit();
Future<bool> remove(String key);
Future<bool> setBool(String key, bool value);
Future<bool> setDouble(String key, double value);
Future<bool> setInt(String key, int value);
Future<bool> setString(String key, String value);
Future<bool> setStringList(String key, List<String> value);

5. Dispose RxSharedPreferences

Finally you dispose RxSharedPreferences to release occupied resources.

rxPrefs.dispose()

Full Examples

  1. Example to populate ListView using RxSharedPreference : here.
  2. Example to Change theme and locale at runtime using RxSharedPreference : here

Read more here.

Share