🌀 Shared preferences with RxDart Stream observation

Overview

rx_shared_preferences alt text

Author: Petrus Nguyễn Thái Học

Codacy Badge Pub Pub codecov Build Status Build example Flutter CI License: MIT Style Hits Latest compatibility result for Stable channel Latest compatibility result for Beta channel Latest compatibility result for Dev channel

All Contributors

  • Shared preference with rxdart Stream observation.
  • Reactive shared preferences for Flutter.
  • Reactive stream wrapper around SharedPreferences.
  • This package provides reactive shared preferences interaction with very little code. It is designed specifically to be used with Flutter and Dart.

Note

Since version 1.3.4, this package is an extension of rx_storage package.

More detail about returned Stream

  • It's a single-subscription Stream (ie. it can only be listened once).

  • Stream will emit the value (nullable) or a TypeError as its first event when it is listen to.

  • It will automatically emit value when value associated with key was changed successfully (emit null when value associated with key was removed or set to null).

  • When value read from Storage has a type other than expected type:

    • If value is null, the Stream will emit null (this occurred because null can be cast to any nullable type).
    • Otherwise, the Stream will emit a TypeError.
  • Can emit two consecutive data events that are equal. You should use Rx operator like distinct (More commonly known as distinctUntilChanged in other Rx implementations) to create an Stream where data events are skipped if they are equal to the previous data event.

Key changed:  |----------K1---K2------K1----K1-----K2---------> time
              |                                                
Value stream: |-----@----@------------@-----@-----------------> time
              |    ^                                      
              |    |
              |  Listen(key=K1)
              |
              |  @: nullable value or TypeError

Getting Started

In your flutter project, add the dependency to your pubspec.yaml

dependencies:
  ...
  rx_shared_preferences: ^2.2.0

Usage

1. Import and instatiance

  • Import rx_shared_preferences.
import 'package:rx_shared_preferences/rx_shared_preferences.dart';
  • Wrap your SharedPreferences in a RxSharedPreferences.
// via constructor.
final rxPrefs = RxSharedPreferences(await SharedPreferences.getInstance());
final rxPrefs = RxSharedPreferences(SharedPreferences.getInstance()); // await is optional
final rxPrefs = RxSharedPreferences.getInstance(); // default singleton instance

// via extension.
final rxPrefs = (await SharedPreferences.getInstance()).rx;

NOTE: When using RxSharedPreferences.getInstance() and extension (await SharedPreferences.getInstance()).rx, to config the logger, you can use RxSharedPreferencesConfigs.logger setter.

2. Add a logger (optional)

You can add logger optional parameter to RxSharedPreferences constructor. The logger will log messages about operations (such as read, write) and stream events. This package provides two RxSharedPreferencesLoggers:

  • RxSharedPreferencesDefaultLogger.
  • RxSharedPreferencesEmptyLogger.
final rxPrefs = RxSharedPreferences(
  SharedPreferences.getInstance(),
  kReleaseMode ? null : RxSharedPreferencesDefaultLogger(),
  // disable logging when running in release mode.
);

NOTE: To disable logging when running in release mode, you can pass null or const RxSharedPreferencesEmptyLogger() to RxSharedPreferences constructor or use RxSharedPreferencesConfigs.logger setter.

NOTE: To prevent printing ↓ Disposed successfully → DisposeBag#....

import 'package:disposebag/disposebag.dart' show DisposeBagConfigs;
void main() {
  DisposeBagConfigs.logger = null;
}

3. Select stream and observe

  • Then, just listen Stream, transform Stream through operators such as (map, flatMap, etc...).
  • If you need listen to this Stream many times, you can use broadcast operators such as share, shareValue, publish, publishValue, etc...
// Listen
rxPrefs.getStringListStream('KEY_LIST').listen(print); // [*]

// Broadcast stream
rxPrefs.getStringListStream('KEY_LIST').share();
rxPrefs.getStringListStream('KEY_LIST').shareValue();
rxPrefs.getStringListStream('KEY_LIST').asBroadcastStream();

// Transform stream
rxPrefs.getIntStream('KEY_INT')
  .map((i) => /* Do something cool */)
  .where((i) => /* Filtering */)
  ...

// must **use same rxPrefs** instance when set value and select stream
await rxPrefs.setStringList('KEY_LIST', ['Cool']); // [*] will print ['Cool']
  • In the previous example we re-used the RxSharedPreferences object rxPrefs for all writing operations. All writing operations must go through this object in order to correctly notify subscribers.

  • In Flutter, you:

    • Can create global RxSharedPreferences instance.

    • Can use default singleton instance RxSharedPreferences.getInstance()

    • Can use InheritedWidget/Provider to provide a RxSharedPreferences instance (create it in main function) for all widgets (recommended). See example/main.

// An example for wrong usage.
rxPrefs1.getStringListStream('KEY_LIST').listen(print); // [*]

rxPrefs2.setStringList('KEY_LIST', ['Cool']); // [*] will not print anything
  • Streams APIs (via extension methods).
  Stream<Object?>              getObjectStream(String key, [Decoder<Object?>? decoder]);
  Stream<bool?>                getBoolStream(String key);
  Stream<double?>              getDoubleStream(String key);
  Stream<int?>                 getIntStream(String key);
  Stream<String?>              getStringStream(String key);
  Stream<List<String>?>        getStringListStream(String key);
  Stream<Set<String>>          getKeysStream();
  
  Future<void>                 executeUpdateBool(String key, Transformer<bool?> transformer);
  Future<void>                 executeUpdateDouble(String key, Transformer<double?> transformer);
  Future<void>                 executeUpdateInt(String key, Transformer<int?> transformer);
  Future<void>                 executeUpdateString(String key, Transformer<String?> transformer);
  Future<void>                 executeUpdateStringList(String key, Transformer<List<String>?> transformer);
  • All methods from RxStorage (RxSharedPreferences implements RxStorage).
  Future<void>                 executeUpdate<T extends Object>(String key, Decoder<T?> decoder, Transformer<T?> transformer, Encoder<T?> encoder);
  Stream<T?>                   observe<T extends Object>(String key, Decoder<T?> decoder);
  Stream<Map<String, Object?>> observeAll();
  Future<void>                 dispose();

4. Get and set methods like to SharedPreferences

  • RxSharedPreferences is like to SharedPreferences, it provides read, write functions (via extension methods).
  Future<Object?>              getObject(String key, [Decoder<Object?>? decoder]);
  Future<bool?>                getBool(String key);
  Future<double?>              getDouble(String key);
  Future<int?>                 getInt(String key);
  Future<Set<String>>          getKeys();
  Future<String?>              getString(String key);
  Future<List<String>?>        getStringList(String key);

  Future<Map<String, Object?>> reload();
  Future<void>                 setBool(String key, bool? value);
  Future<void>                 setDouble(String key, double? value);
  Future<void>                 setInt(String key, int? value);
  Future<void>                 setString(String key, String? value);
  Future<void>                 setStringList(String key, List<String>? value);
  • All methods from Storage (RxSharedPreferences implements Storage).
  Future<bool>                 containsKey(String key);
  Future<T?>                   read<T extends Object>(String key, Decoder<T?> decoder);
  Future<Map<String, Object?>> readAll();
  Future<void>                 clear();
  Future<void>                 remove(String key);
  Future<void>                 write<T extends Object>(String key, T? value, Encoder<T?> encoder);

5. Dispose

You can dispose RxSharedPreferences when is no longer needed. Just call rxPrefs.dispose(). Usually you call this method on dispose of a State

Example demo

Simple authentication app with BLoC rxdart pattern Build ListView from Stream using RxSharedPreferences Change theme and locale (language) runtime

License

    Copyright (c) 2019-2021 Petrus Nguyễn Thái Học

Contributors

Thanks goes to these wonderful people (emoji key):


Petrus Nguyễn Thái Học

💻 📖 🚧

This project follows the all-contributors specification. Contributions of any kind welcome!

Comments
Releases(3.0.0)
  • 3.0.0(Jun 3, 2022)

    https://pub.dev/packages/rx_shared_preferences/versions/3.0.0

    • Update dependencies

      • shared_preferences to 2.0.15
      • rx_storage to 2.0.0
      • rxdart to 0.27.4
      • rxdart_ext to 0.2.2
    • Update Flutter constraint to '>=2.8.0'.


    What's Changed

    • Update subosito/flutter-action action to v2 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/37
    • Update subosito/flutter-action action to v2.2.1 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/38
    • Update subosito/flutter-action action to v2.3.0 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/39
    • Upgrade dependencies by @hoc081098 in https://github.com/hoc081098/rx_shared_preferences/pull/41
    • Update actions/setup-java action to v3 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/42
    • chore(deps): update actions/checkout action to v3 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/43
    • chore(deps): update actions/upload-artifact action to v3 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/44
    • chore(deps): update codecov/codecov-action action to v3 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/46
    • chore(deps): update subosito/flutter-action action to v2.4.0 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/47
    • chore: prepare for 3.0.0 by @hoc081098 in https://github.com/hoc081098/rx_shared_preferences/pull/48
    • fix: SharedPreferencesAdapter ~ type 'List<Object?>' is not a subtype of type 'FutureOr<List?>' in type cast by @hoc081098 in https://github.com/hoc081098/rx_shared_preferences/pull/49

    Full Changelog: https://github.com/hoc081098/rx_shared_preferences/compare/2.3.0...3.0.0

    Source code(tar.gz)
    Source code(zip)
  • 2.3.0(Dec 9, 2021)

    https://pub.dev/packages/rx_shared_preferences/versions/2.3.0

    • Change Dart SDK constraint to '>=2.14.0 <3.0.0' and Flutter constraint to '>=2.5.0'.
    • Update shared_preferences to 2.0.10
    • Fix Flutter 2.8.0 analyzer.

    What's Changed

    • Update codecov/codecov-action action to v2.1.0 by @renovate in https://github.com/hoc081098/rx_shared_preferences/pull/36

    Full Changelog: https://github.com/hoc081098/rx_shared_preferences/compare/2.2.0...2.3.0

    Source code(tar.gz)
    Source code(zip)
  • 2.2.0(Sep 12, 2021)

    https://pub.dev/packages/rx_shared_preferences/versions/2.2.0

    • Update dependencies

      • shared_preferences to 2.0.7
      • rx_storage to 1.2.0
      • meta to 1.7.0
      • rxdart to 0.27.2
      • rxdart_ext to 0.1.2
    • Internal: migrated from pedantic to lints.

    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(May 9, 2021)

  • 2.0.0(Apr 30, 2021)

    https://pub.dev/packages/rx_shared_preferences/versions/2.0.0

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0-nullsafety.0(Feb 24, 2021)

  • 1.3.5(Jan 4, 2021)

  • 1.3.4(Dec 18, 2020)

  • 1.3.3(Oct 10, 2020)

  • 1.3.2(Oct 10, 2020)

    1.3.2 - Oct 10, 2020

    • Add extension: RxSharedPreferences get rx for SharedPreferences. This allows writing concise code like this: sharedPreferences.rx.getStringStream('key').

    • Allows changing logger for default singleton instance or extension: RxSharedPreferencesConfig.logger = ...;

    • Internal implementation refactor.

    Source code(tar.gz)
    Source code(zip)
  • 1.3.1(May 28, 2020)

  • 1.3.0(May 28, 2020)

  • 1.2.0(Apr 22, 2020)

    1.2.0 - Apr 20, 2020

    • Breaking change: support for rxdart 0.24.x.
    • Now, returned stream is broadcast stream.
    • Reset default singleton instance after disposing it.
    • Internal implementation refactor.
    Source code(tar.gz)
    Source code(zip)
  • 1.1.1+1(Jan 29, 2020)

  • 1.1.1(Jan 29, 2020)

    1.1.1 - Jan 29, 2020

    • Add getKeysStream method to IRxSharedPreferences.
    • Add constructor RxSharedPreferences.getInstance() that returns default singleton RxSharedPreferences instance.
    • Internal implementation refactor & fix default logger.
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Dec 18, 2019)

  • 1.0.3+1(Aug 9, 2019)

Owner
Petrus Nguyễn Thái Học
Functional & Reactive Programming - Rx Fan 🌰 RxDart - RxKotlin - RxSwift - rxjs 🌸 Android - iOS - Flutter - Node.js - Angular
Petrus Nguyễn Thái Học
Shared preferences typed - A type-safe wrapper around shared preferences, inspired by ts-localstorage

Typed Shared Preferences A type-safe wrapper around shared_preferences, inspired

Philipp Bauer 0 Jan 31, 2022
Note Shared Preferences - Note App Shared Preferences, Using Flutter

NOTE APP SHARED PREFERENCES LOCALIZATION Watch the gif below (lasts 00:08:22)

Tukhtamurodov Sardorbek 1 Jul 8, 2022
Flutter-Shared-Preference - The goal is to learn how to use the shared preferences plugin to save important pieces of information to your device.

Recipe Finder The goal is to learn how to use the shared preferences plugin to save important pieces of information to your device. Final App UI Resou

Ashirbad Swain 1 Jan 1, 2022
An rx stream builder widget that is able to pre-populate a flutter StreamBuilder with data from an rx stream if the stream is either a value or a replay observable.

An rx stream builder widget that is able to pre-populate a flutter StreamBuilder with data from an rx stream if the stream is either a value or a replay observable. For example the RX stream is a BehaviorSubject or a ReplaySubject.

Jon Samwell 8 Jan 22, 2022
Flutter theme demo using riverpod and shared preferences

flutter_theme_demo A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you start

Andree Yosua 0 Dec 27, 2021
Flutter settings manager built on top of Shared Preferences

Settings Manager Flutter settings store built on top of shared preferences. Code Generator for supported types Usage import 'dart:async'; import 'pac

Rody Davis 17 Dec 13, 2022
Flutter Settings Screen with Shared Preferences

Settings Screen with Shared Preferences A library that provides an easy solution to create settings screens with simple and compound options. Features

Barnabás BARTHA 66 Sep 27, 2022
Shared Preferences ile ekran açılma sayacı uygulaması

sayac_uygulamasi A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

null 0 Dec 29, 2021
A package for encrypted shared preferences

Prefs Guard Prefs Guard is a data protection wrapper for local storage (Shared Prefs). supporting both IOS & Android. - Notice :- Use Same GuardType t

null 26 Jun 7, 2022
This example uses a ScrollView, JSON Rest API, Navigation, Alert Pop Up, Progress Indicator, Globals, Images in a shared asset folder, and 100% Shared Code

This example uses a ScrollView, JSON Rest API, Navigation, Alert Pop Up, Progress Indicator, Globals, Images in a shared asset folder, and 100% Shared Code. Now with the ability to login with FaceID, TouchID, and Fingerprint Reader on Android.

Rody Davis 672 Jan 6, 2023
A starter kit for beginner learns with Bloc pattern, RxDart, sqflite, Fluro and Dio to architect a flutter project. This starter kit build an App Store app as a example

Flutter Starter Kit - App Store Example A starter kit for beginner learns with Bloc pattern, RxDart, sqflite, Fluro and Dio to architect a flutter pro

kw101 678 Jan 8, 2023
A Flutter EventBus using RxDart

FlutterRxBus A Flutter EventBus using RxDart GitHub | Pub | Usage 1. Add to pubspec.yaml rxbus: latest version 2. Define Event Any Dart class or Lis

null 25 Sep 22, 2021
Clonning TIX ID with flutter with BLoC Pattern and RxDart

tix_app Cloning TIX ID in Flutter (Currently design only, next i will grab the movies from IMDB api for free) Feature Movies Movies Detail Ticket List

Anggit Prayogo 23 Aug 23, 2021
181011450390-FLUTTER-CHALLENGE - Example GitHub Search app built in Flutter & RxDart

Example GitHub Search app built in Flutter & RxDart Simple app using the Flutter

null 1 Jan 3, 2022
A simple application connected with API (The Movie Database), related to movies. Application created using BLoC pattern and RxDart

MovieApp I will not hide that this is the most difficult application I have done so far (and I am still working on new features). It looks like this (

Adam Dybcio 9 Oct 28, 2022
A simple state management solution that combine the power of inherited widget and rxdart

Inherited RxDart is a state management library that combine the power of InheritedWidget and RxDart, a simple and elegant state management solution for apps of any scale

Nguyễn Ngọc Phước 14 Oct 26, 2022
🚀 User management app built in flutter using clean architecture, MVVM, get it, dio, RxDart, bloc, cubit, getX and provider

?? Go Rest app In this project, we are going to build a user management app using Flutter. We have used the Go REST API to make HTTP request methods.

Sina 99 Aug 14, 2023
Flutter preferences management with crypto capabilities

crypted_preferences Flutter preferences management with crypto capabilities For now preferences are not crypted, I'm waiting for FFI to land :) But yo

Jimmy Aumard 7 Jan 14, 2020