From 1e060e5faa14e0bed5bfd3bbcc5206761664f878 Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Thu, 8 Aug 2019 11:08:47 -0700 Subject: [PATCH 1/5] getInstance() of shared preferences should not call getMap multiple times --- .../lib/shared_preferences.dart | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/shared_preferences/lib/shared_preferences.dart b/packages/shared_preferences/lib/shared_preferences.dart index d013484fa1ad..b95b2038b3f4 100644 --- a/packages/shared_preferences/lib/shared_preferences.dart +++ b/packages/shared_preferences/lib/shared_preferences.dart @@ -18,14 +18,24 @@ class SharedPreferences { SharedPreferences._(this._preferenceCache); static const String _prefix = 'flutter.'; - static SharedPreferences _instance; + static Completer _completer; static Future getInstance() async { - if (_instance == null) { - final Map preferencesMap = - await _getSharedPreferencesMap(); - _instance = SharedPreferences._(preferencesMap); + if (_completer == null) { + _completer = Completer(); + try { + 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); + Future sharedPrefsFuture = _completer.future; + _completer = null; + return sharedPrefsFuture; + } } - return _instance; + return _completer.future; } /// The cache that holds all preferences. @@ -177,6 +187,6 @@ class SharedPreferences { } return null; }); - _instance?.reload(); + _completer?.future.then((SharedPreferences prefs) => prefs.reload()); } } From 9cc9a7a8729fb65d108ff2720d96d77ac403b218 Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Thu, 8 Aug 2019 12:31:37 -0700 Subject: [PATCH 2/5] Fix tests and formatting --- packages/shared_preferences/lib/shared_preferences.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/shared_preferences/lib/shared_preferences.dart b/packages/shared_preferences/lib/shared_preferences.dart index b95b2038b3f4..0f5c1be526b2 100644 --- a/packages/shared_preferences/lib/shared_preferences.dart +++ b/packages/shared_preferences/lib/shared_preferences.dart @@ -26,7 +26,7 @@ class SharedPreferences { final Map preferencesMap = await _getSharedPreferencesMap(); _completer.complete(SharedPreferences._(preferencesMap)); - } on Exception catch(e) { + } 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); @@ -178,7 +178,7 @@ class SharedPreferences { /// Initializes the shared preferences with mock values for testing. /// - /// If the singleton instance has been initialized already, it is automatically reloaded. + /// If the singleton instance has been initialized already, it is nullified. @visibleForTesting static void setMockInitialValues(Map values) { _kChannel.setMockMethodCallHandler((MethodCall methodCall) async { @@ -187,6 +187,6 @@ class SharedPreferences { } return null; }); - _completer?.future.then((SharedPreferences prefs) => prefs.reload()); + _completer = null; } } From 5d61fe9cdc23744b52c3dab620c31ea104c3691e Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Thu, 8 Aug 2019 12:35:39 -0700 Subject: [PATCH 3/5] Fix analyzer warnings --- packages/shared_preferences/lib/shared_preferences.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/shared_preferences/lib/shared_preferences.dart b/packages/shared_preferences/lib/shared_preferences.dart index 0f5c1be526b2..aece19b6e29e 100644 --- a/packages/shared_preferences/lib/shared_preferences.dart +++ b/packages/shared_preferences/lib/shared_preferences.dart @@ -21,7 +21,7 @@ class SharedPreferences { static Completer _completer; static Future getInstance() async { if (_completer == null) { - _completer = Completer(); + _completer = Completer(); try { final Map preferencesMap = await _getSharedPreferencesMap(); @@ -30,7 +30,7 @@ class SharedPreferences { // 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); - Future sharedPrefsFuture = _completer.future; + final Future sharedPrefsFuture = _completer.future; _completer = null; return sharedPrefsFuture; } From 6bb5437686fb3990cec05f6afe24f609016653a9 Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Thu, 8 Aug 2019 12:40:33 -0700 Subject: [PATCH 4/5] Add tests --- .../shared_preferences/test/shared_preferences_test.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/shared_preferences/test/shared_preferences_test.dart b/packages/shared_preferences/test/shared_preferences_test.dart index f9f4bde06ba3..25c7c7e135c2 100755 --- a/packages/shared_preferences/test/shared_preferences_test.dart +++ b/packages/shared_preferences/test/shared_preferences_test.dart @@ -155,6 +155,12 @@ void main() { expect(preferences.getString('String'), kTestValues2['flutter.String']); }); + test('back to back calls should return same instance.', () async { + Future first = SharedPreferences.getInstance(); + Future second = SharedPreferences.getInstance(); + expect(await first, await second); + }); + group('mocking', () { const String _key = 'dummy'; const String _prefixedKey = 'flutter.' + _key; From b78fb92d1d8932fa959ca7b34ac52de046b180f5 Mon Sep 17 00:00:00 2001 From: Mehmet Fidanboylu Date: Thu, 8 Aug 2019 12:43:53 -0700 Subject: [PATCH 5/5] Analyzer fixes --- packages/shared_preferences/test/shared_preferences_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/shared_preferences/test/shared_preferences_test.dart b/packages/shared_preferences/test/shared_preferences_test.dart index 25c7c7e135c2..c0d9068204c9 100755 --- a/packages/shared_preferences/test/shared_preferences_test.dart +++ b/packages/shared_preferences/test/shared_preferences_test.dart @@ -156,8 +156,8 @@ void main() { }); test('back to back calls should return same instance.', () async { - Future first = SharedPreferences.getInstance(); - Future second = SharedPreferences.getInstance(); + final Future first = SharedPreferences.getInstance(); + final Future second = SharedPreferences.getInstance(); expect(await first, await second); });