Shared preferences plugin

pub package

Wraps platform-specific persistent storage for simple data (NSUserDefaults on iOS and macOS, SharedPreferences on Android, etc.). Data may be persisted to disk asynchronously, and there is no guarantee that writes will be persisted to disk after returning, so this plugin must not be used for storing critical data.

Supported data types are int, double, bool, String and List<String>.

Android iOS Linux macOS Web Windows
Support SDK 16+ 12.0+ Any 10.14+ Any Any

Usage

SharedPreferences vs SharedPreferencesAsync vs SharedPreferencesWithCache

Starting with version 2.3.0 there are three available APIs that can be used in this package. SharedPreferences is a legacy API that will be deprecated in the future. We highly encourage any new users of the plugin to use the newer SharedPreferencesAsync or SharedPreferencesWithCache APIs instead.

Consider migrating existing code to one of the new APIs. See below for more information.

Cache and async or sync getters

SharedPreferences and SharedPreferencesWithCache both use a local cache to store preferences. This allows for synchronous get calls after the initial setup call fetches the preferences from the platform. However, The cache can present issues as well:

  • If you are using shared_preferences from multiple isolates, since each isolate has its own singleton and cache.
  • If you are using shared_preferences in multiple engine instances (including those created by plugins that create background contexts on mobile devices, such as firebase_messaging).
  • If you are modifying the underlying system preference store through something other than the shared_preferences plugin, such as native code.

This can be remedied by calling the reload method before using a getter as needed. If most get calls need a reload, consider using SharedPreferencesAsync instead.

SharedPreferencesAsync does not utilize a local cache which causes all calls to be asynchronous calls to the host platforms storage solution. This can be less performant, but should always provide the latest data stored on the native platform regardless of what process was used to store it.

Android platform storage

The SharedPreferences API uses the native Android Shared Preferences tool to store data.

The SharedPreferencesAsync and SharedPreferencesWithCache APIs use DataStore Preferences to store data.

Examples

Here are small examples that show you how to use the API.

SharedPreferences

Write data

// Obtain shared preferences.
final SharedPreferences prefs = await SharedPreferences.getInstance();

// Save an integer value to 'counter' key.
await prefs.setInt('counter', 10);
// Save an boolean value to 'repeat' key.
await prefs.setBool('repeat', true);
// Save an double value to 'decimal' key.
await prefs.setDouble('decimal', 1.5);
// Save an String value to 'action' key.
await prefs.setString('action', 'Start');
// Save an list of strings to 'items' key.
await prefs.setStringList('items', <String>['Earth', 'Moon', 'Sun']);

Read data

// Try reading data from the 'counter' key. If it doesn't exist, returns null.
final int? counter = prefs.getInt('counter');
// Try reading data from the 'repeat' key. If it doesn't exist, returns null.
final bool? repeat = prefs.getBool('repeat');
// Try reading data from the 'decimal' key. If it doesn't exist, returns null.
final double? decimal = prefs.getDouble('decimal');
// Try reading data from the 'action' key. If it doesn't exist, returns null.
final String? action = prefs.getString('action');
// Try reading data from the 'items' key. If it doesn't exist, returns null.
final List<String>? items = prefs.getStringList('items');

Remove an entry

// Remove data for the 'counter' key.
await prefs.remove('counter');

SharedPreferencesAsync

final SharedPreferencesAsync asyncPrefs = SharedPreferencesAsync();

await asyncPrefs.setBool('repeat', true);
await asyncPrefs.setString('action', 'Start');

final bool? repeat = await asyncPrefs.getBool('repeat');
final String? action = await asyncPrefs.getString('action');

await asyncPrefs.remove('repeat');

// Any time a filter option is included as a method parameter, strongly consider
// using it to avoid potentially unwanted side effects.
await asyncPrefs.clear(allowList: <String>{'action', 'repeat'});

SharedPreferencesWithCache

final SharedPreferencesWithCache prefsWithCache =
    await SharedPreferencesWithCache.create(
  cacheOptions: const SharedPreferencesWithCacheOptions(
    // When an allowlist is included, any keys that aren't included cannot be used.
    allowList: <String>{'repeat', 'action'},
  ),
);

await prefsWithCache.setBool('repeat', true);
await prefsWithCache.setString('action', 'Start');

final bool? repeat = prefsWithCache.getBool('repeat');
final String? action = prefsWithCache.getString('action');

await prefsWithCache.remove('repeat');

// Since the filter options are set at creation, they aren't needed during clear.
await prefsWithCache.clear();

Migration and Prefixes

Migrating from SharedPreferences to SharedPreferencesAsync/WithCache

Currently, migration from the older SharedPreferences API to the newer SharedPreferencesAsync or SharedPreferencesWithCache will need to be done manually.

A simple form of this could be fetching all preferences with SharedPreferences and adding them back using SharedPreferencesAsync, then storing a preference indicating that the migration has been done so that future runs don't repeat the migration.

If a migration is not performed before moving to SharedPreferencesAsync or SharedPreferencesWithCache, most (if not all) data will be lost. Android preferences are stored in a new system, and all platforms are likely to have some form of enforced prefix (see below) that would not transfer automatically.

A tool to make this process easier can be tracked here: https://github.com/flutter/flutter/issues/150732

Adding, Removing, or changing prefixes on SharedPreferences

By default, the SharedPreferences class will only read (and write) preferences that begin with the prefix flutter.. This is all handled internally by the plugin and does not require manually adding this prefix.

Alternatively, SharedPreferences can be configured to use any prefix by adding a call to setPrefix before any instances of SharedPreferences are instantiated. Calling setPrefix after an instance of SharedPreferences is created will fail. Setting the prefix to an empty string '' will allow access to all preferences created by any non-flutter versions of the app (for migrating from a native app to flutter).

If the prefix is set to a value such as '' that causes it to read values that were not originally stored by the SharedPreferences, initializing SharedPreferences may fail if any of the values are of types that are not supported by SharedPreferences. In this case, you can set an allowList that contains only preferences of supported types.

If you decide to remove the prefix entirely, you can still access previously created preferences by manually adding the previous prefix flutter. to the beginning of the preference key.

If you have been using SharedPreferences with the default prefix but wish to change to a new prefix, you will need to transform your current preferences manually to add the new prefix otherwise the old preferences will be inaccessible.

Storage location by platform

Platform SharedPreferences SharedPreferencesAsync/WithCache
Android SharedPreferences DataStore Preferences
iOS NSUserDefaults NSUserDefaults
Linux In the XDG_DATA_HOME directory In the XDG_DATA_HOME directory
macOS NSUserDefaults NSUserDefaults
Web LocalStorage LocalStorage
Windows In the roaming AppData directory In the roaming AppData directory

Libraries

shared_preferences