From b04ff46999afa7cf27e5e0036d5a76951727c7d6 Mon Sep 17 00:00:00 2001 From: Tarrin Neal Date: Thu, 18 Jul 2024 11:22:26 -0700 Subject: [PATCH] [shared_preferences] Platform interface for new shared preferences async (#6962) Platform interface portion of https://github.com/flutter/packages/pull/5210 Adds new async api --- .../CHANGELOG.md | 3 +- .../README.md | 14 +- .../in_memory_shared_preferences_async.dart | 158 ++++++++++++++++++ ..._preferences_async_platform_interface.dart | 109 ++++++++++++ .../lib/types.dart | 65 ++++++- .../pubspec.yaml | 2 +- ...thod_channel_shared_preferences_test.dart} | 0 7 files changed, 340 insertions(+), 11 deletions(-) create mode 100644 packages/shared_preferences/shared_preferences_platform_interface/lib/in_memory_shared_preferences_async.dart create mode 100644 packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_async_platform_interface.dart rename packages/shared_preferences/shared_preferences_platform_interface/test/{method_channel_shared_preferences_test.dart => deprecated_method_channel_shared_preferences_test.dart} (100%) diff --git a/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md b/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md index 3966f6525b94..b611dd3cdc03 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 2.4.0 +* Adds `SharedPreferencesAsyncPlatform` API. * Updates minimum supported SDK version to Flutter 3.16/Dart 3.2. ## 2.3.2 diff --git a/packages/shared_preferences/shared_preferences_platform_interface/README.md b/packages/shared_preferences/shared_preferences_platform_interface/README.md index 301ba68ea361..6716fe997c0b 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/README.md +++ b/packages/shared_preferences/shared_preferences_platform_interface/README.md @@ -9,9 +9,16 @@ same interface. # Usage To implement a new platform-specific implementation of `shared_preferences`, extend -[`SharedPreferencesPlatform`][2] with an implementation that performs the -platform-specific behavior, and when you register your plugin, set the default -`SharedPreferencesLoader` by calling the `SharedPreferencesPlatform.loader` setter. +[`SharedPreferencesPlatform`][2] and [`SharedPreferencesAsyncPlatform`][3] with +implementations that perform the platform-specific behaviors, and when you register +your plugin, set the default `SharedPreferencesStorePlatform` and +`SharedPreferencesAsyncPlatform` by calling the `SharedPreferencesPlatform.instance` +and `SharedPreferencesAsyncPlatform.instance` setters. + +Please note that the plugin tooling only registers the native and/or Dart classes +listed in your package's `pubspec.yaml`, so if you intend to implement more than +one class, you will need to manually register the second class +(as can be seen in the Android and iOS implementations). # Note on breaking changes @@ -23,3 +30,4 @@ on why a less-clean interface is preferable to a breaking change. [1]: ../shared_preferences [2]: lib/shared_preferences_platform_interface.dart +[3]: lib/shared_preferences_async_platform_interface.dart \ No newline at end of file diff --git a/packages/shared_preferences/shared_preferences_platform_interface/lib/in_memory_shared_preferences_async.dart b/packages/shared_preferences/shared_preferences_platform_interface/lib/in_memory_shared_preferences_async.dart new file mode 100644 index 000000000000..5080241814b5 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_platform_interface/lib/in_memory_shared_preferences_async.dart @@ -0,0 +1,158 @@ +// 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 'dart:async'; + +import 'shared_preferences_async_platform_interface.dart'; +import 'types.dart'; + +/// Stores data in memory. +/// +/// Data does not persist across application restarts. This is useful in unit tests. +base class InMemorySharedPreferencesAsync + extends SharedPreferencesAsyncPlatform { + /// Instantiates an empty in-memory preferences store. + InMemorySharedPreferencesAsync.empty() : _data = {}; + + /// Instantiates an in-memory preferences store containing a copy of [data]. + InMemorySharedPreferencesAsync.withData(Map data) + : _data = Map.from(data); + + final Map _data; + + @override + Future clear( + ClearPreferencesParameters parameters, + SharedPreferencesOptions options, + ) async { + final PreferencesFilters filter = parameters.filter; + if (filter.allowList != null) { + _data.removeWhere((String key, _) => filter.allowList!.contains(key)); + } else { + _data.clear(); + } + return true; + } + + @override + Future> getPreferences( + GetPreferencesParameters parameters, + SharedPreferencesOptions options, + ) async { + final PreferencesFilters filter = parameters.filter; + final Map preferences = Map.from(_data); + preferences.removeWhere((String key, _) => + filter.allowList != null && !filter.allowList!.contains(key)); + return preferences; + } + + Future _setValue( + String key, + Object value, + SharedPreferencesOptions options, + ) async { + _data[key] = value; + return true; + } + + @override + Future setString( + String key, + String value, + SharedPreferencesOptions options, + ) async { + return _setValue(key, value, options); + } + + @override + Future setInt( + String key, + int value, + SharedPreferencesOptions options, + ) async { + return _setValue(key, value, options); + } + + @override + Future setDouble( + String key, + double value, + SharedPreferencesOptions options, + ) async { + return _setValue(key, value, options); + } + + @override + Future setBool( + String key, + bool value, + SharedPreferencesOptions options, + ) async { + return _setValue(key, value, options); + } + + @override + Future setStringList( + String key, + List value, + SharedPreferencesOptions options, + ) async { + return _setValue(key, value, options); + } + + @override + Future getString( + String key, + SharedPreferencesOptions options, + ) async { + return _data[key] as String?; + } + + @override + Future getBool( + String key, + SharedPreferencesOptions options, + ) async { + return _data[key] as bool?; + } + + @override + Future getDouble( + String key, + SharedPreferencesOptions options, + ) async { + return _data[key] as double?; + } + + @override + Future getInt( + String key, + SharedPreferencesOptions options, + ) async { + return _data[key] as int?; + } + + @override + Future?> getStringList( + String key, + SharedPreferencesOptions options, + ) async { + final List? data = _data[key] as List?; + return data?.cast(); + } + + @override + Future> getKeys( + GetPreferencesParameters parameters, + SharedPreferencesOptions options, + ) async { + final Set keys = _data.keys.toSet(); + if (parameters.filter.allowList != null) { + keys.retainWhere( + (String element) => parameters.filter.allowList!.contains(element)); + } + + return keys; + } +} diff --git a/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_async_platform_interface.dart b/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_async_platform_interface.dart new file mode 100644 index 000000000000..559483b83647 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_async_platform_interface.dart @@ -0,0 +1,109 @@ +// 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 'dart:async'; + +import 'types.dart'; + +/// The interface that implementations of shared_preferences_async must implement. +abstract base class SharedPreferencesAsyncPlatform { + /// Constructs a SharedPreferencesAsyncPlatform. + SharedPreferencesAsyncPlatform(); + + /// The instance of [SharedPreferencesAsyncPlatform] to use. + static SharedPreferencesAsyncPlatform? instance; + + /// Stores the String [value] associated with the [key]. + Future setString( + String key, + String value, + SharedPreferencesOptions options, + ); + + /// Stores the bool [value] associated with the [key]. + Future setBool( + String key, + bool value, + SharedPreferencesOptions options, + ); + + /// Stores the double [value] associated with the [key]. + Future setDouble( + String key, + double value, + SharedPreferencesOptions options, + ); + + /// Stores the int [value] associated with the [key]. + Future setInt( + String key, + int value, + SharedPreferencesOptions options, + ); + + /// Stores the List [value] associated with the [key]. + Future setStringList( + String key, + List value, + SharedPreferencesOptions options, + ); + + /// Retrieves the String [value] associated with the [key], if any. + /// + /// Throws a [TypeError] if the returned type is not a String. + Future getString( + String key, + SharedPreferencesOptions options, + ); + + /// Retrieves the bool [value] associated with the [key], if any. + /// + /// Throws a [TypeError] if the returned type is not a bool. + Future getBool( + String key, + SharedPreferencesOptions options, + ); + + /// Retrieves the double [value] associated with the [key], if any. + /// + /// Throws a [TypeError] if the returned type is not a double. + Future getDouble( + String key, + SharedPreferencesOptions options, + ); + + /// Retrieves the int [value] associated with the [key], if any. + /// + /// Throws a [TypeError] if the returned type is not an int. + Future getInt( + String key, + SharedPreferencesOptions options, + ); + + /// Retrieves the List [value] associated with the [key], if any. + /// + /// Throws a [TypeError] if the returned type is not a List. + Future?> getStringList( + String key, + SharedPreferencesOptions options, + ); + + /// Removes all keys and values in the store that match the given [parameters]. + Future clear( + ClearPreferencesParameters parameters, + SharedPreferencesOptions options, + ); + + /// Returns all key/value pairs persisting in this store that match the given [parameters]. + Future> getPreferences( + GetPreferencesParameters parameters, + SharedPreferencesOptions options, + ); + + /// Returns all keys persisting in this store that match the given [parameters]. + Future> getKeys( + GetPreferencesParameters parameters, + SharedPreferencesOptions options, + ); +} diff --git a/packages/shared_preferences/shared_preferences_platform_interface/lib/types.dart b/packages/shared_preferences/shared_preferences_platform_interface/lib/types.dart index f52f07194e2d..979361c17e84 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/lib/types.dart +++ b/packages/shared_preferences/shared_preferences_platform_interface/lib/types.dart @@ -2,9 +2,62 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/// Filter options used to get and clear preferences. +// shared_preferences_async types. + +import 'package:flutter/foundation.dart'; + +/// Basic options for creating SharedPreferencesAsync classes. +/// +/// This class exists to provide extension to platform specific options as +/// there are currently no general options that are not platform specific. +@immutable +class SharedPreferencesOptions { + /// Constructor for SharedPreferencesOptions. + const SharedPreferencesOptions(); +} + +/// Filter options used to get and clear preferences on shared_preferences_async. +@immutable +class PreferencesFilters { + /// Creates a new instance with the given options. + const PreferencesFilters({ + this.allowList, + }); + + /// A list of preference keys that will limit getting and clearing to only + /// items included in this list. + /// + /// An empty set will create a filter that allows no items to be set/get. + final Set? allowList; +} + +/// Parameters for use in [get] methods on shared_preferences_async. +@immutable +class GetPreferencesParameters { + /// Creates a new instance with the given options. + const GetPreferencesParameters({required this.filter}); + + /// Filter to limit which preferences are returned. + final PreferencesFilters filter; +} + +/// Parameters for use in [clear] methods on shared_preferences_async. +@immutable +class ClearPreferencesParameters { + /// Creates a new instance with the given options. + const ClearPreferencesParameters({required this.filter}); + + /// Filter to limit which preferences are cleared. + final PreferencesFilters filter; +} + +////////////////////////////////// +// legacy_shared_preferences types. +////////////////////////////////// + +/// Filter options used to get and clear preferences on legacy_shared_preferences. class PreferencesFilter { - /// Constructor. + /// Creates a new instance with the given options. PreferencesFilter({ required this.prefix, this.allowList, @@ -19,18 +72,18 @@ class PreferencesFilter { Set? allowList; } -/// Parameters for use in [getAll] methods. +/// Parameters for use in [getAll] methods on legacy_shared_preferences. class GetAllParameters { - /// Constructor. + /// Creates a new instance with the given options. GetAllParameters({required this.filter}); /// Filter to limit which preferences are returned. PreferencesFilter filter; } -/// Parameters for use in [clear] methods. +/// Parameters for use in [clear] methods on legacy_shared_preferences. class ClearParameters { - /// Constructor. + /// Creates a new instance with the given options. ClearParameters({required this.filter}); /// Filter to limit which preferences are cleared. diff --git a/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml b/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml index c8c98325957c..8d909560b0e4 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: shared_preferences_platform_interface description: A common platform interface for the shared_preferences plugin. repository: https://github.com/flutter/packages/tree/main/packages/shared_preferences/shared_preferences_platform_interface issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22 -version: 2.3.2 +version: 2.4.0 environment: sdk: ^3.2.0 diff --git a/packages/shared_preferences/shared_preferences_platform_interface/test/method_channel_shared_preferences_test.dart b/packages/shared_preferences/shared_preferences_platform_interface/test/deprecated_method_channel_shared_preferences_test.dart similarity index 100% rename from packages/shared_preferences/shared_preferences_platform_interface/test/method_channel_shared_preferences_test.dart rename to packages/shared_preferences/shared_preferences_platform_interface/test/deprecated_method_channel_shared_preferences_test.dart