Skip to content

Commit d2b1c87

Browse files
committed
Shared prefs async and with cache, doc changes on plat int
1 parent 315ed8a commit d2b1c87

File tree

16 files changed

+2433
-459
lines changed

16 files changed

+2433
-459
lines changed

packages/shared_preferences/shared_preferences/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## NEXT
1+
## 2.3.0
22

3+
* Adds `SharedPreferencesAsync` and `SharedPreferencesWithCache` APIs.
34
* Updates minimum supported SDK version to Flutter 3.16/Dart 3.2.
45

56
## 2.2.3

packages/shared_preferences/shared_preferences/README.md

Lines changed: 106 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,48 @@ Supported data types are `int`, `double`, `bool`, `String` and `List<String>`.
1717

1818
## Usage
1919

20-
### Examples
20+
## SharedPreferences vs SharedPreferencesAsync vs SharedPreferencesWithCache
21+
22+
As of the 2.3.0 update there are three available APIs that can be used in this package.
23+
[SharedPreferences] is a legacy API that will be deprecated in the future. We highly encourage
24+
any new users of the plugin to use the newer [SharedPreferencesAsync] or [SharedPreferencesWithCache]
25+
APIs instead.
26+
27+
Consider migrating existing code to one of the new APIs. See [below](#migrating-from-sharedpreferences-to-sharedpreferencesasyncwithcache)
28+
for more information.
29+
30+
### Cache and async or sync getters
31+
32+
[SharedPreferences] and [SharedPreferencesWithCache] both utilize a local cache to store preferences.
33+
This allows for synchronous get calls after the initial setup call fetches the preferences from the platform.
34+
However, The cache can present issues as well:
35+
36+
- If you are using `shared_preferences` from multiple isolates, since each
37+
isolate has its own singleton and cache.
38+
- If you are using `shared_preferences` in multiple engine instances (including
39+
those created by plugins that create background contexts on mobile devices,
40+
such as `firebase_messaging`).
41+
- If you are modifying the underlying system preference store through something
42+
other than the `shared_preferences` plugin, such as native code.
43+
44+
This can be remedied by calling the `reload` method before using a getter as needed.
45+
If most get calls need a reload, consider using [SharedPreferencesAsync] instead.
46+
47+
[SharedPreferencesAsync] does not utilize a local cache which causes all calls to be asynchronous
48+
calls to the host platforms storage solution. This can be less performant, but should always provide the
49+
latest data stored on the native platform regardless of what process was used to store it.
50+
51+
### Android platform storage
52+
53+
The [SharedPreferences] API uses the native [Android Shared Preferences](https://developer.android.com/reference/android/content/SharedPreferences) tool to store data.
54+
55+
The [SharedPreferencesAsync] and [SharedPreferencesWithCache] APIs use [DataStore Preferences](https://developer.android.com/topic/libraries/architecture/datastore) to store data.
56+
57+
## Examples
2158
Here are small examples that show you how to use the API.
2259

60+
### SharedPreferences
61+
2362
#### Write data
2463
<?code-excerpt "readme_excerpts.dart (Write)"?>
2564
```dart
@@ -60,32 +99,70 @@ final List<String>? items = prefs.getStringList('items');
6099
await prefs.remove('counter');
61100
```
62101

63-
### Multiple instances
102+
### SharedPreferencesAsync
103+
<?code-excerpt "readme_excerpts.dart (Async)"?>
104+
```dart
105+
final SharedPreferencesAsync asyncPrefs = SharedPreferencesAsync();
64106
65-
In order to make preference lookup via the `get*` methods synchronous,
66-
`shared_preferences` uses a cache on the Dart side, which is normally only
67-
updated by the `set*` methods. Usually this is an implementation detail that
68-
does not affect callers, but it can cause issues in a few cases:
69-
- If you are using `shared_preferences` from multiple isolates, since each
70-
isolate has its own `SharedPreferences` singleton and cache.
71-
- If you are using `shared_preferences` in multiple engine instances (including
72-
those created by plugins that create background contexts on mobile devices,
73-
such as `firebase_messaging`).
74-
- If you are modifying the underlying system preference store through something
75-
other than the `shared_preferences` plugin, such as native code.
107+
await asyncPrefs.setBool('repeat', true);
108+
await asyncPrefs.setString('action', 'Start');
109+
110+
final bool? repeat = await asyncPrefs.getBool('repeat');
111+
final String? action = await asyncPrefs.getString('action');
112+
113+
await asyncPrefs.remove('repeat');
114+
115+
// Any time a filter option is included as a method parameter, it is highly recommended
116+
// that it is used to avoid potentially unwanted side effects.
117+
await asyncPrefs.clear(const ClearPreferencesParameters(
118+
filter: PreferencesFilters(allowList: <String>{'action', 'repeat'})));
119+
```
76120

77-
If you need to read a preference value that may have been changed by anything
78-
other than the `SharedPreferences` instance you are reading it from, you should
79-
call `reload()` on the instance before reading from it to update its cache with
80-
any external changes.
121+
### SharedPreferencesWithCache
122+
<?code-excerpt "readme_excerpts.dart (WithCache)"?>
123+
```dart
124+
final SharedPreferencesWithCache prefsWithCache =
125+
await SharedPreferencesWithCache.create(
126+
cacheOptions: const SharedPreferencesWithCacheOptions(
127+
filter: PreferencesFilters(
128+
// When an allowlist is included, any keys that aren't included cannot be used.
129+
allowList: <String>{'repeat', 'action'},
130+
),
131+
),
132+
);
133+
134+
await prefsWithCache.setBool('repeat', true);
135+
await prefsWithCache.setString('action', 'Start');
136+
137+
final bool? repeat = prefsWithCache.getBool('repeat');
138+
final String? action = prefsWithCache.getString('action');
139+
140+
await prefsWithCache.remove('repeat');
141+
142+
// Since the filter options are set at creation, they aren't needed during clear.
143+
await prefsWithCache.clear();
144+
```
81145

82-
If this is problematic for your use case, you can thumbs up
83-
[this issue](https://github.com/flutter/flutter/issues/123078) to express
84-
interest in APIs that provide direct (asynchronous) access to the underlying
85-
preference store, and/or subscribe to it for updates.
86146

87147
### Migration and Prefixes
88148

149+
#### Migrating from SharedPreferences to SharedPreferencesAsync/WithCache
150+
151+
Currently, migration from the older [SharedPreferences] API to the newer
152+
[SharedPreferencesAsync] or [SharedPreferencesWithCache] will need to be done manually.
153+
154+
A simple form of this could be fetching all preferences with [SharedPreferences] and adding
155+
them back using [SharedPreferencesAsync], then storing a preference indicating that the
156+
migration has been done so that future runs don't repeat the migration.
157+
158+
If a migration is not performed before moving to [SharedPreferencesAsync] or [SharedPreferencesWithCache],
159+
most (if not all) data will be lost. Android preferences are stored in a new system, and all platforms
160+
are likely to have some form of enforced prefix (see below) that would not transfer automatically.
161+
162+
A tool to make this process easier can be tracked here: https://github.com/flutter/flutter/issues/150732
163+
164+
#### Adding, Removing, or changing prefixes on SharedPreferences
165+
89166
By default, the `SharedPreferences` plugin will only read (and write) preferences
90167
that begin with the prefix `flutter.`. This is all handled internally by the plugin
91168
and does not require manually adding this prefix.
@@ -123,11 +200,11 @@ SharedPreferences.setMockInitialValues(values);
123200

124201
### Storage location by platform
125202

126-
| Platform | Location |
127-
| :--- | :--- |
128-
| Android | SharedPreferences |
129-
| iOS | NSUserDefaults |
130-
| Linux | In the XDG_DATA_HOME directory |
131-
| macOS | NSUserDefaults |
132-
| Web | LocalStorage |
133-
| Windows | In the roaming AppData directory |
203+
| Platform | SharedPreferences | SharedPreferencesAsync/WithCache |
204+
| :--- | :--- | :--- |
205+
| Android | SharedPreferences | DataStore Preferences |
206+
| iOS | NSUserDefaults | NSUserDefaults |
207+
| Linux | In the XDG_DATA_HOME directory | In the XDG_DATA_HOME directory |
208+
| macOS | NSUserDefaults | NSUserDefaults |
209+
| Web | LocalStorage | LocalStorage |
210+
| Windows | In the roaming AppData directory | In the roaming AppData directory |

0 commit comments

Comments
 (0)