diff --git a/.gitignore b/.gitignore index 734169649fd3..54133a3b3a84 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ keystore.properties 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 35344bfb898c..000000000000 --- 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 15a50475078d..487ec1db8a33 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 5c7f0b0fda12..46daeff6706f 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 @@ class SharedPreferencesDemoState extends State { 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 1c09e2eb867e..b693df2131ed 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 @@ void main() { 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 ff6e9ce74ad9..f3aa9e218d82 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 @@ Future main() async { 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 c82116a57437..62160dee20fd 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 @@ class SharedPreferences { static const String _prefix = 'flutter.'; static Completer _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 @@ class SharedPreferences { Future remove(String key) => _setValue(null, key, null); Future _setValue(String valueType, String key, Object value) { - final Map params = { - 'key': '$_prefix$key', - }; + final String prefixedKey = '$_prefix$key'; if (value == null) { _preferenceCache.remove(key); - return _kChannel - .invokeMethod('remove', params) - .then((dynamic result) => result); + return _store.remove(prefixedKey); } else { if (value is List) { // Make a copy of the list so that later mutations won't propagate @@ -139,22 +136,19 @@ class SharedPreferences { } else { _preferenceCache[key] = value; } - params['value'] = value; - return _kChannel - .invokeMethod('set$valueType', params) - .then((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 commit() async => await _kChannel.invokeMethod('commit'); + Future commit() async => true; /// Completes with true once the user preferences for the app has been cleared. - Future clear() async { + Future clear() { _preferenceCache.clear(); - return await _kChannel.invokeMethod('clear'); + return _store.clear(); } /// Fetches the latest values from the host platform. @@ -169,8 +163,7 @@ class SharedPreferences { } static Future> _getSharedPreferencesMap() async { - final Map fromSystem = - await _kChannel.invokeMapMethod('getAll'); + final Map fromSystem = await _store.getAll(); assert(fromSystem != null); // Strip the flutter. prefix from the returned preferences. final Map preferencesMap = {}; @@ -194,12 +187,8 @@ class SharedPreferences { } return MapEntry(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 62853949d055..c9f6d335b869 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+7 +version: 0.5.4+8 flutter: plugin: @@ -15,6 +15,7 @@ dependencies: 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 d171f7ae7f05..b219774d1992 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 kTestValues = { 'flutter.String': 'hello world', 'flutter.bool': true, @@ -30,23 +27,18 @@ void main() { 'flutter.List': ['baz', 'quox'], }; - final List log = []; + 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 @@ void main() { expect(preferences.getInt('int'), kTestValues['flutter.int']); expect(preferences.getDouble('double'), kTestValues['flutter.double']); expect(preferences.getStringList('List'), kTestValues['flutter.List']); - expect(log, []); + expect(store.log, []); }); test('writing', () async { @@ -72,56 +64,60 @@ void main() { preferences.setStringList('List', kTestValues2['flutter.List']) ]); expect( - log, + store.log, [ - isMethodCall('setString', arguments: { - 'key': 'flutter.String', - 'value': kTestValues2['flutter.String'] - }), - isMethodCall('setBool', arguments: { - 'key': 'flutter.bool', - 'value': kTestValues2['flutter.bool'] - }), - isMethodCall('setInt', arguments: { - 'key': 'flutter.int', - 'value': kTestValues2['flutter.int'] - }), - isMethodCall('setDouble', arguments: { - 'key': 'flutter.double', - 'value': kTestValues2['flutter.double'] - }), - isMethodCall('setStringList', arguments: { - 'key': 'flutter.List', - 'value': kTestValues2['flutter.List'] - }), + isMethodCall('setValue', arguments: [ + 'String', + 'flutter.String', + kTestValues2['flutter.String'], + ]), + isMethodCall('setValue', arguments: [ + 'Bool', + 'flutter.bool', + kTestValues2['flutter.bool'], + ]), + isMethodCall('setValue', arguments: [ + 'Int', + 'flutter.int', + kTestValues2['flutter.int'], + ]), + isMethodCall('setValue', arguments: [ + 'Double', + 'flutter.double', + kTestValues2['flutter.double'], + ]), + isMethodCall('setValue', arguments: [ + '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([])); + expect(store.log, equals([])); }); 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.filled( 6, isMethodCall( 'remove', - arguments: {'key': 'flutter.$key'}, + arguments: 'flutter.$key', ), growable: true, )); @@ -132,7 +128,7 @@ void main() { expect(false, preferences.containsKey(key)); - preferences.setString(key, 'test'); + await preferences.setString(key, 'test'); expect(true, preferences.containsKey(key)); }); @@ -143,7 +139,7 @@ void main() { expect(preferences.getInt('int'), null); expect(preferences.getDouble('double'), null); expect(preferences.getStringList('List'), null); - expect(log, [isMethodCall('clear', arguments: null)]); + expect(store.log, [isMethodCall('clear', arguments: null)]); }); test('reloading', () async { @@ -207,3 +203,38 @@ void main() { expect(value, 'foo'); }); } + +class FakeSharedPreferencesStore implements SharedPreferencesStorePlatform { + FakeSharedPreferencesStore(Map data) + : backend = InMemorySharedPreferencesStore.withData(data); + + final InMemorySharedPreferencesStore backend; + final List log = []; + + @override + bool get isMock => true; + + @override + Future clear() { + log.add(MethodCall('clear')); + return backend.clear(); + } + + @override + Future> getAll() { + log.add(MethodCall('getAll')); + return backend.getAll(); + } + + @override + Future remove(String key) { + log.add(MethodCall('remove', key)); + return backend.remove(key); + } + + @override + Future setValue(String valueType, String key, Object value) { + log.add(MethodCall('setValue', [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 1028ee607386..903924fd322a 100755 --- a/script/build_all_plugins_app.sh +++ b/script/build_all_plugins_app.sh @@ -15,6 +15,7 @@ readonly EXCLUDED_PLUGINS_LIST=( "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[*]}")