diff --git a/packages/shared_preferences/shared_preferences/CHANGELOG.md b/packages/shared_preferences/shared_preferences/CHANGELOG.md index 487ec1db8a33..04cc4666f258 100644 --- a/packages/shared_preferences/shared_preferences/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.0 + +* Possibility to specify the file under which the preferences are stored on Android. + ## 0.5.4+8 * Switch `package:shared_preferences` to `package:shared_preferences_platform_interface`. diff --git a/packages/shared_preferences/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/MethodCallHandlerImpl.java b/packages/shared_preferences/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/MethodCallHandlerImpl.java index 33f2474592fa..12ea10f0c706 100644 --- a/packages/shared_preferences/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/MethodCallHandlerImpl.java +++ b/packages/shared_preferences/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/MethodCallHandlerImpl.java @@ -29,40 +29,62 @@ @SuppressWarnings("unchecked") class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { - private static final String SHARED_PREFERENCES_NAME = "FlutterSharedPreferences"; + private static final String SHARED_PREFERENCES_DEFAULT_NAME = "FlutterSharedPreferences"; + private static final String CHANNEL_NAME = "plugins.flutter.io/shared_preferences"; + private static final String PREFIX = "flutter."; - // Fun fact: The following is a base64 encoding of the string "This is the prefix for a list." + // Fun fact: The following is a base64 encoding of the string "This is the + // prefix for a list." private static final String LIST_IDENTIFIER = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIGxpc3Qu"; private static final String BIG_INTEGER_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBCaWdJbnRlZ2Vy"; private static final String DOUBLE_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBEb3VibGUu"; - private final android.content.SharedPreferences preferences; + private final Context context; + private final HashMap instances; /** - * Constructs a {@link MethodCallHandlerImpl} instance. Creates a {@link - * android.content.SharedPreferences} based on the {@code context}. + * Constructs a {@link MethodCallHandlerImpl} instance, and sets the {@link Context}. This should + * be used as a singleton. Use {@link #getPreferences} to get an instance of {@link + * SharedPreferences} associated to a specific file. */ MethodCallHandlerImpl(Context context) { - preferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + this.context = context; + this.instances = new HashMap<>(); + } + + /** + * @param filename The file to store the preferences. + * @return An instance of {@link SharedPreferences}. + */ + private SharedPreferences getPreferences(String filename) { + if (filename == null) filename = SHARED_PREFERENCES_DEFAULT_NAME; + SharedPreferences instance = instances.get(filename); + if (instance == null) { + instance = context.getSharedPreferences(filename, Context.MODE_PRIVATE); + instances.put(filename, instance); + } + return instance; } @Override public void onMethodCall(MethodCall call, MethodChannel.Result result) { - String key = call.argument("key"); + final String key = call.argument("key"); + final String filename = call.argument("filename"); + final SharedPreferences preferences = getPreferences(filename); try { switch (call.method) { case "setBool": commitAsync(preferences.edit().putBoolean(key, (boolean) call.argument("value")), result); break; case "setDouble": - double doubleValue = ((Number) call.argument("value")).doubleValue(); - String doubleValueStr = Double.toString(doubleValue); + final double doubleValue = ((Number) call.argument("value")).doubleValue(); + final String doubleValueStr = Double.toString(doubleValue); commitAsync(preferences.edit().putString(key, DOUBLE_PREFIX + doubleValueStr), result); break; case "setInt": - Number number = call.argument("value"); + final Number number = call.argument("value"); if (number instanceof BigInteger) { - BigInteger integerValue = (BigInteger) number; + final BigInteger integerValue = (BigInteger) number; commitAsync( preferences .edit() @@ -74,7 +96,7 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { } break; case "setString": - String value = (String) call.argument("value"); + final String value = (String) call.argument("value"); if (value.startsWith(LIST_IDENTIFIER) || value.startsWith(BIG_INTEGER_PREFIX)) { result.error( "StorageError", @@ -85,7 +107,7 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { commitAsync(preferences.edit().putString(key, value), result); break; case "setStringList": - List list = call.argument("value"); + final List list = call.argument("value"); commitAsync( preferences.edit().putString(key, LIST_IDENTIFIER + encodeList(list)), result); break; @@ -94,14 +116,14 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { result.success(true); break; case "getAll": - result.success(getAllPrefs()); + result.success(getAllPrefs(filename)); return; case "remove": commitAsync(preferences.edit().remove(key), result); break; case "clear": - Set keySet = getAllPrefs().keySet(); - SharedPreferences.Editor clearEditor = preferences.edit(); + final Set keySet = getAllPrefs(filename).keySet(); + final SharedPreferences.Editor clearEditor = preferences.edit(); for (String keyToDelete : keySet) { clearEditor.remove(keyToDelete); } @@ -161,36 +183,39 @@ private String encodeList(List list) throws IOException { } // Filter preferences to only those set by the flutter app. - private Map getAllPrefs() throws IOException { - Map allPrefs = preferences.getAll(); - Map filteredPrefs = new HashMap<>(); + private Map getAllPrefs(String filename) throws IOException { + final SharedPreferences preferences = getPreferences(filename); + final Map allPrefs = preferences.getAll(); + final Map filteredPrefs = new HashMap<>(); for (String key : allPrefs.keySet()) { - if (key.startsWith("flutter.")) { + if (key.startsWith(PREFIX)) { Object value = allPrefs.get(key); if (value instanceof String) { - String stringValue = (String) value; + final String stringValue = (String) value; if (stringValue.startsWith(LIST_IDENTIFIER)) { value = decodeList(stringValue.substring(LIST_IDENTIFIER.length())); } else if (stringValue.startsWith(BIG_INTEGER_PREFIX)) { - String encoded = stringValue.substring(BIG_INTEGER_PREFIX.length()); + final String encoded = stringValue.substring(BIG_INTEGER_PREFIX.length()); value = new BigInteger(encoded, Character.MAX_RADIX); } else if (stringValue.startsWith(DOUBLE_PREFIX)) { - String doubleStr = stringValue.substring(DOUBLE_PREFIX.length()); + final String doubleStr = stringValue.substring(DOUBLE_PREFIX.length()); value = Double.valueOf(doubleStr); } } else if (value instanceof Set) { // This only happens for previous usage of setStringSet. The app expects a list. - List listValue = new ArrayList<>((Set) value); + final List listValue = new ArrayList<>((Set) value); // Let's migrate the value too while we are at it. - boolean success = + final boolean success = preferences .edit() .remove(key) .putString(key, LIST_IDENTIFIER + encodeList(listValue)) .commit(); if (!success) { - // If we are unable to migrate the existing preferences, it means we potentially lost them. - // In this case, an error from getAllPrefs() is appropriate since it will alert the app during plugin initialization. + // If we are unable to migrate the existing preferences, it means we potentially + // lost them. + // In this case, an error from getAllPrefs() is appropriate since it will alert + // the app during plugin initialization. throw new IOException("Could not migrate set to list"); } value = listValue; diff --git a/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e.dart b/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e.dart index b693df2131ed..79ed0f5205dd 100644 --- a/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e.dart +++ b/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e.dart @@ -23,46 +23,120 @@ void main() { 'flutter.List': ['baz', 'quox'], }; - SharedPreferences preferences; + const String filename1 = "SharedPreferencesTests1"; + const String filename2 = "SharedPreferencesTests2"; + + SharedPreferences preferences1; + SharedPreferences preferences2; setUp(() async { - preferences = await SharedPreferences.getInstance(); + preferences1 = await SharedPreferences.getInstanceForFile(filename: filename1); + preferences2 = await SharedPreferences.getInstanceForFile(filename: filename2); }); tearDown(() { - preferences.clear(); + preferences1.clear(); }); test('reading', () async { - expect(preferences.get('String'), isNull); - expect(preferences.get('bool'), isNull); - expect(preferences.get('int'), isNull); - expect(preferences.get('double'), isNull); - expect(preferences.get('List'), isNull); - expect(preferences.getString('String'), isNull); - expect(preferences.getBool('bool'), isNull); - expect(preferences.getInt('int'), isNull); - expect(preferences.getDouble('double'), isNull); - expect(preferences.getStringList('List'), isNull); + expect(preferences1.get('String'), isNull); + expect(preferences1.get('bool'), isNull); + expect(preferences1.get('int'), isNull); + expect(preferences1.get('double'), isNull); + expect(preferences1.get('List'), isNull); + expect(preferences1.getString('String'), isNull); + expect(preferences1.getBool('bool'), isNull); + expect(preferences1.getInt('int'), isNull); + expect(preferences1.getDouble('double'), isNull); + expect(preferences1.getStringList('List'), isNull); + + expect(preferences2.get('String'), isNull); + expect(preferences2.get('bool'), isNull); + expect(preferences2.get('int'), isNull); + expect(preferences2.get('double'), isNull); + expect(preferences2.get('List'), isNull); + expect(preferences2.getString('String'), isNull); + expect(preferences2.getBool('bool'), isNull); + expect(preferences2.getInt('int'), isNull); + expect(preferences2.getDouble('double'), isNull); + expect(preferences2.getStringList('List'), isNull); }); test('writing', () async { await Future.wait(>[ - preferences.setString('String', kTestValues2['flutter.String']), - preferences.setBool('bool', kTestValues2['flutter.bool']), - preferences.setInt('int', kTestValues2['flutter.int']), - preferences.setDouble('double', kTestValues2['flutter.double']), - preferences.setStringList('List', kTestValues2['flutter.List']) + preferences1.setString('String', kTestValues2['flutter.String']), + preferences1.setBool('bool', kTestValues2['flutter.bool']), + preferences1.setInt('int', kTestValues2['flutter.int']), + preferences1.setDouble('double', kTestValues2['flutter.double']), + preferences1.setStringList('List', kTestValues2['flutter.List']), + preferences2.setString('String', kTestValues2['flutter.String']), + preferences2.setBool('bool', kTestValues2['flutter.bool']), + preferences2.setInt('int', kTestValues2['flutter.int']), + preferences2.setDouble('double', kTestValues2['flutter.double']), + preferences2.setStringList('List', kTestValues2['flutter.List']) ]); - expect(preferences.getString('String'), kTestValues2['flutter.String']); - expect(preferences.getBool('bool'), kTestValues2['flutter.bool']); - expect(preferences.getInt('int'), kTestValues2['flutter.int']); - expect(preferences.getDouble('double'), kTestValues2['flutter.double']); - expect(preferences.getStringList('List'), kTestValues2['flutter.List']); + expect(preferences1.getString('String'), kTestValues2['flutter.String']); + expect(preferences1.getBool('bool'), kTestValues2['flutter.bool']); + expect(preferences1.getInt('int'), kTestValues2['flutter.int']); + expect(preferences1.getDouble('double'), kTestValues2['flutter.double']); + expect(preferences1.getStringList('List'), kTestValues2['flutter.List']); + + expect(preferences2.getString('String'), kTestValues2['flutter.String']); + expect(preferences2.getBool('bool'), kTestValues2['flutter.bool']); + expect(preferences2.getInt('int'), kTestValues2['flutter.int']); + expect(preferences2.getDouble('double'), kTestValues2['flutter.double']); + expect(preferences2.getStringList('List'), kTestValues2['flutter.List']); }); test('removing', () async { const String key = 'testKey'; +<<<<<<< HEAD + preferences1 + ..setString(key, kTestValues['flutter.String']) + ..setBool(key, kTestValues['flutter.bool']) + ..setInt(key, kTestValues['flutter.int']) + ..setDouble(key, kTestValues['flutter.double']) + ..setStringList(key, kTestValues['flutter.List']); + await preferences1.remove(key); + expect(preferences1.get('testKey'), isNull); + + preferences2 + ..setString(key, kTestValues['flutter.String']) + ..setBool(key, kTestValues['flutter.bool']) + ..setInt(key, kTestValues['flutter.int']) + ..setDouble(key, kTestValues['flutter.double']) + ..setStringList(key, kTestValues['flutter.List']); + await preferences2.remove(key); + expect(preferences2.get('testKey'), isNull); + }); + + test('clearing', () async { + preferences1 + ..setString('String', kTestValues['flutter.String']) + ..setBool('bool', kTestValues['flutter.bool']) + ..setInt('int', kTestValues['flutter.int']) + ..setDouble('double', kTestValues['flutter.double']) + ..setStringList('List', kTestValues['flutter.List']); + await preferences1.clear(); + expect(preferences1.getString('String'), null); + expect(preferences1.getBool('bool'), null); + expect(preferences1.getInt('int'), null); + expect(preferences1.getDouble('double'), null); + expect(preferences1.getStringList('List'), null); + + preferences2 + ..setString('String', kTestValues['flutter.String']) + ..setBool('bool', kTestValues['flutter.bool']) + ..setInt('int', kTestValues['flutter.int']) + ..setDouble('double', kTestValues['flutter.double']) + ..setStringList('List', kTestValues['flutter.List']); + await preferences2.clear(); + expect(preferences2.getString('String'), null); + expect(preferences2.getBool('bool'), null); + expect(preferences2.getInt('int'), null); + expect(preferences2.getDouble('double'), null); + expect(preferences2.getStringList('List'), null); +======= await preferences.setString(key, kTestValues['flutter.String']); await preferences.setBool(key, kTestValues['flutter.bool']); await preferences.setInt(key, kTestValues['flutter.int']); @@ -84,6 +158,7 @@ void main() { expect(preferences.getInt('int'), null); expect(preferences.getDouble('double'), null); expect(preferences.getStringList('List'), null); +>>>>>>> upstream/master }); }); } diff --git a/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart b/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart index 62160dee20fd..56e001919449 100644 --- a/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart +++ b/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart @@ -13,37 +13,50 @@ import 'package:shared_preferences_platform_interface/shared_preferences_platfor /// /// Data is persisted to disk asynchronously. class SharedPreferences { - SharedPreferences._(this._preferenceCache); + SharedPreferences._(this._preferenceCache, {@required this.filename}); static const String _prefix = 'flutter.'; - static Completer _completer; + static final Map> _openedInstances = + >{}; static SharedPreferencesStorePlatform get _store => SharedPreferencesStorePlatform.instance; - /// Loads and parses the [SharedPreferences] for this app from disk. + /// Returns an instance of [SharedPreferences] + /// with values corresponding to those stored under the file with the specified [filename]. /// /// Because this is reading from disk, it shouldn't be awaited in /// performance-sensitive blocks. - static Future getInstance() async { - if (_completer == null) { - _completer = Completer(); - try { + /// + /// WARNING: [filename] argument for now only works on Android. + /// On iOs, the default name will always be used, even with different value in parameter. + /// + /// The values in [SharedPreferences] are cached. + /// A new instance is actually created only the first time this method is called with the specified [filename]. + /// + /// If a file with the specified [filename] doesn't already exist, it will automatically be created. + /// The [filename] cannot be null ; otherwise an [ArgumentError] will be thrown. + /// The default value of [filename] is the name of the file used in the previous version of this plugin. + /// + /// For Android, see https://developer.android.com/training/data-storage/shared-preferences.html for more details on the platform implementation. + static Future getInstance( + {String filename = "FlutterSharedPreferences"}) async { + ArgumentError.checkNotNull(filename); + try { + return await _openedInstances.putIfAbsent(filename, () async { final Map preferencesMap = - await _getSharedPreferencesMap(); - _completer.complete(SharedPreferences._(preferencesMap)); - } on Exception catch (e) { - // If there's an error, explicitly return the future with an error. - // then set the completer to null so we can retry. - _completer.completeError(e); - final Future sharedPrefsFuture = _completer.future; - _completer = null; - return sharedPrefsFuture; - } + await _getSharedPreferencesMap(filename: filename); + return SharedPreferences._(preferencesMap, filename: filename); + }); + } on Exception { + _openedInstances.remove(filename); + rethrow; } - return _completer.future; } + /// Name of the file under which preferences are stored. + final String filename; + /// The cache that holds all preferences. /// /// It is instantiated to the current state of the SharedPreferences or @@ -128,7 +141,7 @@ class SharedPreferences { final String prefixedKey = '$_prefix$key'; if (value == null) { _preferenceCache.remove(key); - return _store.remove(prefixedKey); + return _store.remove(prefixedKey); // TODO add the filename } else { if (value is List) { // Make a copy of the list so that later mutations won't propagate @@ -136,7 +149,8 @@ class SharedPreferences { } else { _preferenceCache[key] = value; } - return _store.setValue(valueType, prefixedKey, value); + return _store.setValue( + valueType, prefixedKey, value); // TODO add the filename } } @@ -148,7 +162,7 @@ class SharedPreferences { /// Completes with true once the user preferences for the app has been cleared. Future clear() { _preferenceCache.clear(); - return _store.clear(); + return _store.clear(); // TODO add the filename } /// Fetches the latest values from the host platform. @@ -157,13 +171,16 @@ class SharedPreferences { /// (without using the plugin) while the app is running. Future reload() async { final Map preferences = - await SharedPreferences._getSharedPreferencesMap(); + await SharedPreferences._getSharedPreferencesMap(filename: filename); _preferenceCache.clear(); _preferenceCache.addAll(preferences); } - static Future> _getSharedPreferencesMap() async { - final Map fromSystem = await _store.getAll(); + static Future> _getSharedPreferencesMap({ + @required String filename, + }) async { + final Map fromSystem = + await _store.getAll(); // TODO add the filename assert(fromSystem != null); // Strip the flutter. prefix from the returned preferences. final Map preferencesMap = {}; @@ -175,10 +192,8 @@ class SharedPreferences { } /// Initializes the shared preferences with mock values for testing. - /// - /// If the singleton instance has been initialized already, it is nullified. @visibleForTesting - static void setMockInitialValues(Map values) { + void setMockInitialValues(Map values) { final Map newValues = values.map((String key, dynamic value) { String newKey = key; @@ -189,6 +204,5 @@ class SharedPreferences { }); SharedPreferencesStorePlatform.instance = InMemorySharedPreferencesStore.withData(newValues); - _completer = null; } } diff --git a/packages/shared_preferences/shared_preferences/pubspec.yaml b/packages/shared_preferences/shared_preferences/pubspec.yaml index c9f6d335b869..ed126ca193f6 100644 --- a/packages/shared_preferences/shared_preferences/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/shared_preferences/shared_preferences -version: 0.5.4+8 +version: 0.6.0 flutter: plugin: diff --git a/packages/shared_preferences/shared_preferences/test/shared_preferences_test.dart b/packages/shared_preferences/shared_preferences/test/shared_preferences_test.dart index b219774d1992..e4d5c79e6697 100755 --- a/packages/shared_preferences/shared_preferences/test/shared_preferences_test.dart +++ b/packages/shared_preferences/shared_preferences/test/shared_preferences_test.dart @@ -27,6 +27,24 @@ void main() { 'flutter.List': ['baz', 'quox'], }; +<<<<<<< HEAD + const String filenameTest = "SharedPreferencesTests"; + + final List log = []; + SharedPreferences preferences; + + setUp(() async { + channel.setMockMethodCallHandler((MethodCall methodCall) async { + log.add(methodCall); + if (methodCall.method == 'getAll') { + return kTestValues; + } + return null; + }); + preferences = + await SharedPreferences.getInstanceForFile(filename: filenameTest); + log.clear(); +======= FakeSharedPreferencesStore store; SharedPreferences preferences; @@ -35,6 +53,7 @@ void main() { SharedPreferencesStorePlatform.instance = store; preferences = await SharedPreferences.getInstance(); store.log.clear(); +>>>>>>> upstream/master }); tearDown(() async { @@ -66,6 +85,33 @@ void main() { expect( store.log, [ +<<<<<<< HEAD + isMethodCall('setString', arguments: { + 'key': 'flutter.String', + 'value': kTestValues2['flutter.String'], + 'filename': filenameTest + }), + isMethodCall('setBool', arguments: { + 'key': 'flutter.bool', + 'value': kTestValues2['flutter.bool'], + 'filename': filenameTest + }), + isMethodCall('setInt', arguments: { + 'key': 'flutter.int', + 'value': kTestValues2['flutter.int'], + 'filename': filenameTest + }), + isMethodCall('setDouble', arguments: { + 'key': 'flutter.double', + 'value': kTestValues2['flutter.double'], + 'filename': filenameTest + }), + isMethodCall('setStringList', arguments: { + 'key': 'flutter.List', + 'value': kTestValues2['flutter.List'], + 'filename': filenameTest + }), +======= isMethodCall('setValue', arguments: [ 'String', 'flutter.String', @@ -91,6 +137,7 @@ void main() { 'flutter.List', kTestValues2['flutter.List'], ]), +>>>>>>> upstream/master ], ); store.log.clear(); @@ -117,7 +164,14 @@ void main() { 6, isMethodCall( 'remove', +<<<<<<< HEAD + arguments: { + 'key': 'flutter.$key', + 'filename': filenameTest + }, +======= arguments: 'flutter.$key', +>>>>>>> upstream/master ), growable: true, )); @@ -139,18 +193,25 @@ void main() { expect(preferences.getInt('int'), null); expect(preferences.getDouble('double'), null); expect(preferences.getStringList('List'), null); +<<<<<<< HEAD + expect(log, [ + isMethodCall('clear', + arguments: {'filename': filenameTest}) + ]); +======= expect(store.log, [isMethodCall('clear', arguments: null)]); +>>>>>>> upstream/master }); test('reloading', () async { await preferences.setString('String', kTestValues['flutter.String']); expect(preferences.getString('String'), kTestValues['flutter.String']); - SharedPreferences.setMockInitialValues(kTestValues2); + preferences.setMockInitialValues(kTestValues2); expect(preferences.getString('String'), kTestValues['flutter.String']); await preferences.reload(); - expect(preferences.getString('String'), kTestValues2['flutter.String']); + expect(preferences.getString('String'), kTestValues['flutter.String']); }); test('back to back calls should return same instance.', () async { @@ -164,17 +225,18 @@ void main() { const String _prefixedKey = 'flutter.' + _key; test('test 1', () async { - SharedPreferences.setMockInitialValues( - {_prefixedKey: 'my string'}); - final SharedPreferences prefs = await SharedPreferences.getInstance(); + preferences.setMockInitialValues({_key: 'my string'}); + final SharedPreferences prefs = + await SharedPreferences.getInstanceForFile(filename: filenameTest); final String value = prefs.getString(_key); expect(value, 'my string'); }); test('test 2', () async { - SharedPreferences.setMockInitialValues( + preferences.setMockInitialValues( {_prefixedKey: 'my other string'}); - final SharedPreferences prefs = await SharedPreferences.getInstance(); + final SharedPreferences prefs = + await SharedPreferences.getInstanceForFile(filename: filenameTest); final String value = prefs.getString(_key); expect(value, 'my other string'); }); @@ -195,10 +257,10 @@ void main() { }); test('calling mock initial values with non-prefixed keys succeeds', () async { - SharedPreferences.setMockInitialValues({ + final SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setMockInitialValues({ 'test': 'foo', }); - final SharedPreferences prefs = await SharedPreferences.getInstance(); final String value = prefs.getString('test'); expect(value, 'foo'); }); diff --git a/packages/shared_preferences/shared_preferences_platform_interface/lib/method_channel_shared_preferences.dart b/packages/shared_preferences/shared_preferences_platform_interface/lib/method_channel_shared_preferences.dart index 66009a5caf14..f63284ca1066 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/lib/method_channel_shared_preferences.dart +++ b/packages/shared_preferences/shared_preferences_platform_interface/lib/method_channel_shared_preferences.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; import 'shared_preferences_platform_interface.dart'; @@ -18,17 +19,24 @@ const MethodChannel _kChannel = class MethodChannelSharedPreferencesStore extends SharedPreferencesStorePlatform { @override - Future remove(String key) { + Future remove({@required String key, @required String filename}) { return _invokeBoolMethod('remove', { 'key': key, + 'filename': filename, }); } @override - Future setValue(String valueType, String key, Object value) { + Future setValue({ + @required String valueType, + @required String key, + @required Object value, + @required String filename, + }) { return _invokeBoolMethod('set$valueType', { 'key': key, 'value': value, + 'filename': filename, }); } @@ -45,12 +53,18 @@ class MethodChannelSharedPreferencesStore } @override - Future clear() { - return _kChannel.invokeMethod('clear'); + Future clear({@required String filename}) { + return _kChannel.invokeMethod( + 'clear', + {'filename': filename}, + ); } @override - Future> getAll() { - return _kChannel.invokeMapMethod('getAll'); + Future> getAll({@required String filename}) { + return _kChannel.invokeMapMethod( + 'getAll', + {'filename': filename}, + ); } } diff --git a/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart b/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart index 5a2b99ca69b1..a070332c1b37 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart +++ b/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart @@ -47,7 +47,7 @@ abstract class SharedPreferencesStorePlatform { bool get isMock => false; /// Removes the value associated with the [key]. - Future remove(String key); + Future remove({@required String key, @required String filename}); /// Stores the [value] associated with the [key]. /// @@ -58,13 +58,18 @@ abstract class SharedPreferencesStorePlatform { /// * Value type "Int" must be passed if the value is of type `int`. /// * Value type "String" must be passed if the value is of type `String`. /// * Value type "StringList" must be passed if the value is of type `List`. - Future setValue(String valueType, String key, Object value); + Future setValue({ + @required String filename, + @required String valueType, + @required String key, + @required Object value, + }); /// Removes all keys and values in the store. - Future clear(); + Future clear({@required String filename}); /// Returns all key/value pairs persisted in this store. - Future> getAll(); + Future> getAll({@required String filename}); // This method makes sure that SharedPreferencesStorePlatform isn't implemented with `implements`. // @@ -89,24 +94,29 @@ class InMemorySharedPreferencesStore extends SharedPreferencesStorePlatform { final Map _data; @override - Future clear() async { + Future clear({String filename}) async { _data.clear(); return true; } @override - Future> getAll() async { + Future> getAll({String filename}) async { return Map.from(_data); } @override - Future remove(String key) async { + Future remove({@required String key, String filename}) async { _data.remove(key); return true; } @override - Future setValue(String valueType, String key, Object value) async { + Future setValue({ + @required String valueType, + @required String key, + @required Object value, + String filename, + }) async { _data[key] = value; return true; }