diff --git a/packages/shared_preferences/shared_preferences/CHANGELOG.md b/packages/shared_preferences/shared_preferences/CHANGELOG.md index 9980dfecb6d..3449842a263 100644 --- a/packages/shared_preferences/shared_preferences/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2.5.3 +* Fixes a bug in the example app. + ## 2.5.2 * Fixes `setState` returning `Future` on `example/main.dart` error in example code. diff --git a/packages/shared_preferences/shared_preferences/example/lib/main.dart b/packages/shared_preferences/shared_preferences/example/lib/main.dart index 48624fba469..68103057247 100644 --- a/packages/shared_preferences/shared_preferences/example/lib/main.dart +++ b/packages/shared_preferences/shared_preferences/example/lib/main.dart @@ -44,6 +44,10 @@ class SharedPreferencesDemoState extends State { late Future _counter; int _externalCounter = 0; + /// Completes when the preferences have been initialized, which happens after + /// legacy preferences have been migrated. + final Completer _preferencesReady = Completer(); + Future _incrementCounter() async { final SharedPreferencesWithCache prefs = await _prefs; final int counter = (prefs.getInt('counter') ?? 0) + 1; @@ -86,6 +90,7 @@ class SharedPreferencesDemoState extends State { return prefs.getInt('counter') ?? 0; }); _getExternalCounter(); + _preferencesReady.complete(); }); } @@ -96,25 +101,30 @@ class SharedPreferencesDemoState extends State { title: const Text('SharedPreferencesWithCache Demo'), ), body: Center( - child: FutureBuilder( - future: _counter, - builder: (BuildContext context, AsyncSnapshot snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.none: - case ConnectionState.waiting: - return const CircularProgressIndicator(); - case ConnectionState.active: - case ConnectionState.done: - if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else { - return Text( - 'Button tapped ${snapshot.data ?? 0 + _externalCounter} time${(snapshot.data ?? 0 + _externalCounter) == 1 ? '' : 's'}.\n\n' - 'This should persist across restarts.', - ); - } - } - })), + child: _WaitForInitialization( + initialized: _preferencesReady.future, + builder: (BuildContext context) => FutureBuilder( + future: _counter, + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + case ConnectionState.waiting: + return const CircularProgressIndicator(); + case ConnectionState.active: + case ConnectionState.done: + if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + return Text( + 'Button tapped ${snapshot.data ?? 0 + _externalCounter} time${(snapshot.data ?? 0 + _externalCounter) == 1 ? '' : 's'}.\n\n' + 'This should persist across restarts.', + ); + } + } + }, + ), + ), + ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', @@ -123,3 +133,28 @@ class SharedPreferencesDemoState extends State { ); } } + +/// Waits for the [initialized] future to complete before rendering [builder]. +class _WaitForInitialization extends StatelessWidget { + const _WaitForInitialization({ + required this.initialized, + required this.builder, + }); + + final Future initialized; + final WidgetBuilder builder; + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: initialized, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.waiting || + snapshot.connectionState == ConnectionState.none) { + return const CircularProgressIndicator(); + } + return builder(context); + }, + ); + } +} diff --git a/packages/shared_preferences/shared_preferences/example/test/example_app_test.dart b/packages/shared_preferences/shared_preferences/example/test/example_app_test.dart new file mode 100644 index 00000000000..3c8549b6b9c --- /dev/null +++ b/packages/shared_preferences/shared_preferences/example/test/example_app_test.dart @@ -0,0 +1,123 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:shared_preferences_example/main.dart'; +import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart'; +import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart'; +import 'package:shared_preferences_platform_interface/types.dart'; + +void main() { + group('SharedPreferences example app', () { + setUp(() { + SharedPreferencesAsyncPlatform.instance = FakeSharedPreferencesAsync(); + }); + + tearDown(() { + SharedPreferencesAsyncPlatform.instance = null; + }); + + testWidgets('builds successfully', (WidgetTester tester) async { + await tester.pumpWidget(const MyApp()); + }); + }); +} + +// Note: this code is duplicated in +// shared_preferences/test/shared_preferences_async_test.dart. Since we cannot +// import the relative path ../../test/shared_preferences_async_test.dart on the +// web platform, we had to copy it here for use in this test library. +base class FakeSharedPreferencesAsync extends SharedPreferencesAsyncPlatform { + final InMemorySharedPreferencesAsync backend = + InMemorySharedPreferencesAsync.empty(); + final List log = []; + + @override + Future clear( + ClearPreferencesParameters parameters, SharedPreferencesOptions options) { + log.add(MethodCall('clear', [...?parameters.filter.allowList])); + return backend.clear(parameters, options); + } + + @override + Future getBool(String key, SharedPreferencesOptions options) { + log.add(MethodCall('getBool', [key])); + return backend.getBool(key, options); + } + + @override + Future getDouble(String key, SharedPreferencesOptions options) { + log.add(MethodCall('getDouble', [key])); + return backend.getDouble(key, options); + } + + @override + Future getInt(String key, SharedPreferencesOptions options) { + log.add(MethodCall('getInt', [key])); + return backend.getInt(key, options); + } + + @override + Future> getKeys( + GetPreferencesParameters parameters, SharedPreferencesOptions options) { + log.add(MethodCall('getKeys', [...?parameters.filter.allowList])); + return backend.getKeys(parameters, options); + } + + @override + Future> getPreferences( + GetPreferencesParameters parameters, SharedPreferencesOptions options) { + log.add(MethodCall( + 'getPreferences', [...?parameters.filter.allowList])); + return backend.getPreferences(parameters, options); + } + + @override + Future getString(String key, SharedPreferencesOptions options) { + log.add(MethodCall('getString', [key])); + return backend.getString(key, options); + } + + @override + Future?> getStringList( + String key, SharedPreferencesOptions options) { + log.add(MethodCall('getStringList', [key])); + return backend.getStringList(key, options); + } + + @override + Future setBool( + String key, bool value, SharedPreferencesOptions options) { + log.add(MethodCall('setBool', [key, value])); + return backend.setBool(key, value, options); + } + + @override + Future setDouble( + String key, double value, SharedPreferencesOptions options) { + log.add(MethodCall('setDouble', [key, value])); + return backend.setDouble(key, value, options); + } + + @override + Future setInt(String key, int value, SharedPreferencesOptions options) { + log.add(MethodCall('setInt', [key, value])); + return backend.setInt(key, value, options); + } + + @override + Future setString( + String key, String value, SharedPreferencesOptions options) { + log.add(MethodCall('setString', [key, value])); + return backend.setString(key, value, options); + } + + @override + Future setStringList( + String key, List value, SharedPreferencesOptions options) { + log.add(MethodCall('setStringList', [key, value])); + return backend.setStringList(key, value, options); + } +} diff --git a/packages/shared_preferences/shared_preferences/pubspec.yaml b/packages/shared_preferences/shared_preferences/pubspec.yaml index 3f535a86a02..ca545d084d8 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. repository: https://github.com/flutter/packages/tree/main/packages/shared_preferences/shared_preferences issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22 -version: 2.5.2 +version: 2.5.3 environment: sdk: ^3.5.0