Implement shared_preferences on top of platform interface (#2325)
* implement shared_preferences on top of platform interface
diff --git a/.gitignore b/.gitignore
index 7341696..54133a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@
gradlew
gradlew.bat
gradle-wrapper.jar
+.flutter-plugins-dependencies
*.iml
GeneratedPluginRegistrant.h
diff --git a/packages/shared_preferences/analysis_options.yaml b/packages/shared_preferences/analysis_options.yaml
deleted file mode 100644
index 35344bf..0000000
--- a/packages/shared_preferences/analysis_options.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-# This is a temporary file to allow us to land a new set of linter rules in a
-# series of manageable patches instead of one gigantic PR. It disables some of
-# the new lints that are already failing on this plugin, for this plugin. It
-# should be deleted and the failing lints addressed as soon as possible.
-
-include: ../../analysis_options.yaml
-
-analyzer:
- errors:
- curly_braces_in_flow_control_structures: ignore
- unawaited_futures: ignore
diff --git a/packages/shared_preferences/shared_preferences/CHANGELOG.md b/packages/shared_preferences/shared_preferences/CHANGELOG.md
index 15a5047..487ec1d 100644
--- a/packages/shared_preferences/shared_preferences/CHANGELOG.md
+++ b/packages/shared_preferences/shared_preferences/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.5.4+8
+
+* Switch `package:shared_preferences` to `package:shared_preferences_platform_interface`.
+ No code changes are necessary in Flutter apps. This is not a breaking change.
+
## 0.5.4+7
* Restructure the project for Web support.
diff --git a/packages/shared_preferences/shared_preferences/example/lib/main.dart b/packages/shared_preferences/shared_preferences/example/lib/main.dart
index 5c7f0b0..46daeff 100644
--- a/packages/shared_preferences/shared_preferences/example/lib/main.dart
+++ b/packages/shared_preferences/shared_preferences/example/lib/main.dart
@@ -67,13 +67,14 @@
case ConnectionState.waiting:
return const CircularProgressIndicator();
default:
- if (snapshot.hasError)
+ if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
- else
+ } else {
return Text(
'Button tapped ${snapshot.data} time${snapshot.data == 1 ? '' : 's'}.\n\n'
'This should persist across restarts.',
);
+ }
}
})),
floatingActionButton: FloatingActionButton(
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 1c09e2e..b693df2 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
@@ -63,23 +63,21 @@
test('removing', () async {
const String key = 'testKey';
- preferences
- ..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 preferences.setString(key, kTestValues['flutter.String']);
+ await preferences.setBool(key, kTestValues['flutter.bool']);
+ await preferences.setInt(key, kTestValues['flutter.int']);
+ await preferences.setDouble(key, kTestValues['flutter.double']);
+ await preferences.setStringList(key, kTestValues['flutter.List']);
await preferences.remove(key);
expect(preferences.get('testKey'), isNull);
});
test('clearing', () async {
- preferences
- ..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 preferences.setString('String', kTestValues['flutter.String']);
+ await preferences.setBool('bool', kTestValues['flutter.bool']);
+ await preferences.setInt('int', kTestValues['flutter.int']);
+ await preferences.setDouble('double', kTestValues['flutter.double']);
+ await preferences.setStringList('List', kTestValues['flutter.List']);
await preferences.clear();
expect(preferences.getString('String'), null);
expect(preferences.getBool('bool'), null);
diff --git a/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e_test.dart b/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e_test.dart
index ff6e9ce..f3aa9e2 100644
--- a/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e_test.dart
+++ b/packages/shared_preferences/shared_preferences/example/test_driver/shared_preferences_e2e_test.dart
@@ -10,6 +10,6 @@
final FlutterDriver driver = await FlutterDriver.connect();
final String result =
await driver.requestData(null, timeout: const Duration(minutes: 1));
- driver.close();
+ await driver.close();
exit(result == 'pass' ? 0 : 1);
}
diff --git a/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart b/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart
index c82116a..62160de 100644
--- a/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart
+++ b/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart
@@ -4,11 +4,9 @@
import 'dart:async';
-import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
-const MethodChannel _kChannel =
- MethodChannel('plugins.flutter.io/shared_preferences');
+import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart';
/// Wraps NSUserDefaults (on iOS) and SharedPreferences (on Android), providing
/// a persistent store for simple data.
@@ -20,6 +18,9 @@
static const String _prefix = 'flutter.';
static Completer<SharedPreferences> _completer;
+ static SharedPreferencesStorePlatform get _store =>
+ SharedPreferencesStorePlatform.instance;
+
/// Loads and parses the [SharedPreferences] for this app from disk.
///
/// Because this is reading from disk, it shouldn't be awaited in
@@ -124,14 +125,10 @@
Future<bool> remove(String key) => _setValue(null, key, null);
Future<bool> _setValue(String valueType, String key, Object value) {
- final Map<String, dynamic> params = <String, dynamic>{
- 'key': '$_prefix$key',
- };
+ final String prefixedKey = '$_prefix$key';
if (value == null) {
_preferenceCache.remove(key);
- return _kChannel
- .invokeMethod<bool>('remove', params)
- .then<bool>((dynamic result) => result);
+ return _store.remove(prefixedKey);
} else {
if (value is List<String>) {
// Make a copy of the list so that later mutations won't propagate
@@ -139,22 +136,19 @@
} else {
_preferenceCache[key] = value;
}
- params['value'] = value;
- return _kChannel
- .invokeMethod<bool>('set$valueType', params)
- .then<bool>((dynamic result) => result);
+ return _store.setValue(valueType, prefixedKey, value);
}
}
/// Always returns true.
/// On iOS, synchronize is marked deprecated. On Android, we commit every set.
@deprecated
- Future<bool> commit() async => await _kChannel.invokeMethod<bool>('commit');
+ Future<bool> commit() async => true;
/// Completes with true once the user preferences for the app has been cleared.
- Future<bool> clear() async {
+ Future<bool> clear() {
_preferenceCache.clear();
- return await _kChannel.invokeMethod<bool>('clear');
+ return _store.clear();
}
/// Fetches the latest values from the host platform.
@@ -169,8 +163,7 @@
}
static Future<Map<String, Object>> _getSharedPreferencesMap() async {
- final Map<String, Object> fromSystem =
- await _kChannel.invokeMapMethod<String, Object>('getAll');
+ final Map<String, Object> fromSystem = await _store.getAll();
assert(fromSystem != null);
// Strip the flutter. prefix from the returned preferences.
final Map<String, Object> preferencesMap = <String, Object>{};
@@ -194,12 +187,8 @@
}
return MapEntry<String, dynamic>(newKey, value);
});
- _kChannel.setMockMethodCallHandler((MethodCall methodCall) async {
- if (methodCall.method == 'getAll') {
- return newValues;
- }
- return null;
- });
+ 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 6285394..c9f6d33 100644
--- a/packages/shared_preferences/shared_preferences/pubspec.yaml
+++ b/packages/shared_preferences/shared_preferences/pubspec.yaml
@@ -3,7 +3,7 @@
Wraps NSUserDefaults on iOS and SharedPreferences on Android.
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/shared_preferences/shared_preferences
-version: 0.5.4+7
+version: 0.5.4+8
flutter:
plugin:
@@ -15,6 +15,7 @@
meta: ^1.0.4
flutter:
sdk: flutter
+ shared_preferences_platform_interface: ^1.0.0
dev_dependencies:
flutter_test:
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 d171f7a..b219774 100755
--- a/packages/shared_preferences/shared_preferences/test/shared_preferences_test.dart
+++ b/packages/shared_preferences/shared_preferences/test/shared_preferences_test.dart
@@ -5,15 +5,12 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
- group('$SharedPreferences', () {
- const MethodChannel channel = MethodChannel(
- 'plugins.flutter.io/shared_preferences',
- );
-
+ group('SharedPreferences', () {
const Map<String, dynamic> kTestValues = <String, dynamic>{
'flutter.String': 'hello world',
'flutter.bool': true,
@@ -30,23 +27,18 @@
'flutter.List': <String>['baz', 'quox'],
};
- final List<MethodCall> log = <MethodCall>[];
+ FakeSharedPreferencesStore store;
SharedPreferences preferences;
setUp(() async {
- channel.setMockMethodCallHandler((MethodCall methodCall) async {
- log.add(methodCall);
- if (methodCall.method == 'getAll') {
- return kTestValues;
- }
- return null;
- });
+ store = FakeSharedPreferencesStore(kTestValues);
+ SharedPreferencesStorePlatform.instance = store;
preferences = await SharedPreferences.getInstance();
- log.clear();
+ store.log.clear();
});
- tearDown(() {
- preferences.clear();
+ tearDown(() async {
+ await preferences.clear();
});
test('reading', () async {
@@ -60,7 +52,7 @@
expect(preferences.getInt('int'), kTestValues['flutter.int']);
expect(preferences.getDouble('double'), kTestValues['flutter.double']);
expect(preferences.getStringList('List'), kTestValues['flutter.List']);
- expect(log, <Matcher>[]);
+ expect(store.log, <Matcher>[]);
});
test('writing', () async {
@@ -72,56 +64,60 @@
preferences.setStringList('List', kTestValues2['flutter.List'])
]);
expect(
- log,
+ store.log,
<Matcher>[
- isMethodCall('setString', arguments: <String, dynamic>{
- 'key': 'flutter.String',
- 'value': kTestValues2['flutter.String']
- }),
- isMethodCall('setBool', arguments: <String, dynamic>{
- 'key': 'flutter.bool',
- 'value': kTestValues2['flutter.bool']
- }),
- isMethodCall('setInt', arguments: <String, dynamic>{
- 'key': 'flutter.int',
- 'value': kTestValues2['flutter.int']
- }),
- isMethodCall('setDouble', arguments: <String, dynamic>{
- 'key': 'flutter.double',
- 'value': kTestValues2['flutter.double']
- }),
- isMethodCall('setStringList', arguments: <String, dynamic>{
- 'key': 'flutter.List',
- 'value': kTestValues2['flutter.List']
- }),
+ isMethodCall('setValue', arguments: <dynamic>[
+ 'String',
+ 'flutter.String',
+ kTestValues2['flutter.String'],
+ ]),
+ isMethodCall('setValue', arguments: <dynamic>[
+ 'Bool',
+ 'flutter.bool',
+ kTestValues2['flutter.bool'],
+ ]),
+ isMethodCall('setValue', arguments: <dynamic>[
+ 'Int',
+ 'flutter.int',
+ kTestValues2['flutter.int'],
+ ]),
+ isMethodCall('setValue', arguments: <dynamic>[
+ 'Double',
+ 'flutter.double',
+ kTestValues2['flutter.double'],
+ ]),
+ isMethodCall('setValue', arguments: <dynamic>[
+ 'StringList',
+ 'flutter.List',
+ kTestValues2['flutter.List'],
+ ]),
],
);
- log.clear();
+ store.log.clear();
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(log, equals(<MethodCall>[]));
+ expect(store.log, equals(<MethodCall>[]));
});
test('removing', () async {
const String key = 'testKey';
- preferences
- ..setString(key, null)
- ..setBool(key, null)
- ..setInt(key, null)
- ..setDouble(key, null)
- ..setStringList(key, null);
+ await preferences.setString(key, null);
+ await preferences.setBool(key, null);
+ await preferences.setInt(key, null);
+ await preferences.setDouble(key, null);
+ await preferences.setStringList(key, null);
await preferences.remove(key);
expect(
- log,
+ store.log,
List<Matcher>.filled(
6,
isMethodCall(
'remove',
- arguments: <String, dynamic>{'key': 'flutter.$key'},
+ arguments: 'flutter.$key',
),
growable: true,
));
@@ -132,7 +128,7 @@
expect(false, preferences.containsKey(key));
- preferences.setString(key, 'test');
+ await preferences.setString(key, 'test');
expect(true, preferences.containsKey(key));
});
@@ -143,7 +139,7 @@
expect(preferences.getInt('int'), null);
expect(preferences.getDouble('double'), null);
expect(preferences.getStringList('List'), null);
- expect(log, <Matcher>[isMethodCall('clear', arguments: null)]);
+ expect(store.log, <Matcher>[isMethodCall('clear', arguments: null)]);
});
test('reloading', () async {
@@ -207,3 +203,38 @@
expect(value, 'foo');
});
}
+
+class FakeSharedPreferencesStore implements SharedPreferencesStorePlatform {
+ FakeSharedPreferencesStore(Map<String, Object> data)
+ : backend = InMemorySharedPreferencesStore.withData(data);
+
+ final InMemorySharedPreferencesStore backend;
+ final List<MethodCall> log = <MethodCall>[];
+
+ @override
+ bool get isMock => true;
+
+ @override
+ Future<bool> clear() {
+ log.add(MethodCall('clear'));
+ return backend.clear();
+ }
+
+ @override
+ Future<Map<String, Object>> getAll() {
+ log.add(MethodCall('getAll'));
+ return backend.getAll();
+ }
+
+ @override
+ Future<bool> remove(String key) {
+ log.add(MethodCall('remove', key));
+ return backend.remove(key);
+ }
+
+ @override
+ Future<bool> setValue(String valueType, String key, Object value) {
+ log.add(MethodCall('setValue', <dynamic>[valueType, key, value]));
+ return backend.setValue(valueType, key, value);
+ }
+}
diff --git a/script/build_all_plugins_app.sh b/script/build_all_plugins_app.sh
index 1028ee6..903924f 100755
--- a/script/build_all_plugins_app.sh
+++ b/script/build_all_plugins_app.sh
@@ -15,6 +15,7 @@
"url_launcher_platform_interface"
"google_sign_in_platform_interface"
"video_player_platform_interface"
+ "shared_preferences_platform_interface"
)
# Comma-separated string of the list above
readonly EXCLUDED=$(IFS=, ; echo "${EXCLUDED_PLUGINS_LIST[*]}")