Releases: jozzdart/prf
Release list
v2.4.6
v2.4.5
v2.4.4
v2.4.3
v2.4.2
Hotfix: Web Compatibility for 64-bit Encoded Types
Fixed runtime crash on Flutter Web due to unsupported ByteData.getInt64/setInt64 operations in dart2js.
This affected all prf types storing 64-bit values:
DateTimeList<DateTime>List<Duration>
These types now use manual 64-bit encoding via two 32-bit integers (high/low) to ensure full Web compatibility, with no changes to binary format or migration required.
v2.4.1
✨ New: Custom Casting Adapter with .cast()
You can now easily create custom adapters on-the-fly for types that can be encoded into a native type (int, double, bool, String) using the new .cast() factory on Prf.
This allows you to persist your custom objects without writing a full adapter class, by just providing encode/decode functions.
Example
Let's say you want to store a Locale as an String (milliseconds):
final langPref = Prf.cast<Locale, String>(
'saved_language',
encode: (locale) => locale.languageCode,
decode: (string) => string == null ? null : Locale(string),
);✨ New: getOrDefault() extension method
Added a new method to all prf values:
Future<T> getOrDefault()Returns the value from SharedPreferences, or throws an exception if it's null and no default was defined.
Example:
final coins = 'coins'.prf<int>(defaultValue: 0);
print(await coins.getOrDefault()); // → 0
final level = 'level'.prf<int>(); // no default
print(await level.getOrDefault()); // ❌ throws if not setThis improves error visibility in logic that assumes a non-null value must exist.
Technical Details
- Introduced
EncodedDelegateAdapter<T, TCast>: a flexible adapter that delegates encoding/decoding to provided functions. .cast<T, TCast>()factory wraps this adapter for ergonomic, type-safe usage.- Compatible with all existing
prffeatures (caching, isolated, custom defaults).
v2.4.0
We are officially deprecating all persistent utility services (trackers and limiters) from the prf package. To keep prf focused purely on persistence (without embedded logic), all advanced time-based utilities are being migrated to two new dedicated packages:
Why this change?
- Improves modularity and keeps
prflightweight. - Reduces dependencies for apps that only need persistence.
- Allows
trackandlimitto evolve independently with focused updates. - Removes ~300 extra tests and ~1,200 lines from the README, which had made the package heavy and harder to navigate.
- Frees up space to expand
limitandtrackwith more features and utilities while keepingprfclean, focused, and ~90% smaller in size.
✅ The APIs remain backward-compatible until v3.0 (2026) — just change your imports.
-
limitpackage → https://pub.dev/packages/limitPrfCooldown→CooldownPrfRateLimiter→RateLimiter
-
trackpackage → https://pub.dev/packages/trackPrfStreakTracker→StreakTrackerPrfPeriodicCounter→PeriodicCounterPrfRolloverCounter→RolloverCounterPrfActivityCounter→ActivityCounterPrfHistory→HistoryTracker- Enums:
TrackerPeriod→TimePeriodActivitySpan→TimeSpan
flutter pub add track
flutter pub add limitDeprecated in 2.4.0 (to be removed in v3.0.0 estimated 2026):
- Limit Services:
PrfCooldownPrfRateLimiter - Tracking Services:
PrfStreakTrackerPrfPeriodicCounterPrfRolloverCounterPrfActivityCounterPrfHistory - Enums:
TrackerPeriodActivitySpan - Service Interfaces:
BaseCounterTrackerBaseTracker
Everything related to the services. Nothing changed in prf itself.
v2.3.1
-
Added
PrfHistory<T>: a reusable persisted history tracker for any type. Supports max length trimming, deduplication, isolation safety, and flexible factory constructors for enums and JSON models. Also added.historyTracker(name)extension onPrfAdapter<List<T>>for simplifiedPrfHistory<T>creation. -
Added
.prf<T>()and.prfCustomAdapter<T>()extensions onStringfor quick and concise variable creation.
final coinsPrf = 'player_coins'.prf<int>(); // works with all types now- Added
.prf(key)extension onPrfAdapter<T>for direct use of custom adapters without boilerplate.
final colorPrf = ColorAdapter().prf('saved_color'); // no need to specify types- Added
Prf.jsonList<T>()for easy creation of cached and isolate-safe preferences for lists of JSON-serializable objects. - Added
Prf.enumeratedList<T>()for type-safe enum list preferences backed by nativeList<int>storage. - Added
JsonListAdapter<T>: stores aList<T>where each item is a JSON string using nativeList<String>support. - Added
EnumListAdapter<T>: stores a list of enums as their integer indices using nativeList<int>support. - Fixed broken or incorrect navigation links in the README.
v2.3.0
General Additions
- Added
Back to Table of Contentslinks to all README sections for improved navigation. - All utilities & services now support an optional
useCache: trueparameter to enable faster memory-cached access for single-isolate apps. They remain isolate-safe by default, but enabling caching disables isolate safety. See theREADMEfor guidance on when to enable it. - Added adapters for
List<num>,List<Uint8List>,List<BigInt>,List<Duration>, andList<Uri>. Now the package supports all possible types out of the box!
🧭 Tracker Services
Introduced a suite of new tracker utilities — see the 📖 README for full documentation, examples, and usage tips:
-
PrfStreakTracker— Persistent streak tracker that increases when an action is performed every aligned period (e.g. daily), and resets if a period is missed. Ideal for login streaks, daily habits, and weekly goals. Includes methods for checking streak length, detecting breaks, and calculating time left before expiration. -
PrfPeriodicCounter— A persistent counter that resets itself automatically at the start of each aligned period (e.g. daily, hourly, weekly). Perfect for counting recurring actions like logins or submissions. Supports incrementing, getting, resetting, and clearing the count. -
PrfRolloverCounter— A sliding-window counter that resets itself after a fixed duration (e.g. 10 minutes after last use). Useful for rolling metrics like "actions per hour" or "retry cooldowns". Includes time-aware utilities like time remaining, end time, and percentage elapsed. -
PrfActivityCounter— A time-based analytics tracker that aggregates values over hour, day, month, and year spans. Useful for building heatmaps, tracking activity frequency, or logging usage patterns. Supports advanced queries like.summary(),.total(),.all(), and.maxValue(), with uncapped yearly data retention. -
All tracker tools are now covered by extensive tests — including 220 dedicated tests for the new trackers — to ensure proper state reset, timestamp alignment, and session persistence.
-
These tools are designed for advanced use cases like counters, streaks, timers, and rolling metrics — allowing custom persistent services to be built cleanly and safely. All built on top of `PrfIso — fully isolate-safe.
Fixed
All persistent utilities and services are now fully synchronized.
This version introduces comprehensive internal locking to all Prf-based services and trackers to prevent concurrent access issues in asynchronous or multi-call scenarios.
Previously, state mutations (e.g. .set, .reset, .increment) were not guarded, which could cause race conditions, corrupted values, or inconsistent behavior — especially in rapid or concurrent calls.
This update ensures:
- Atomic updates to counters, cooldowns, and streaks.
- No race conditions between
.get(),.set(), and.reset(). - Consistency across isolates or concurrent flows.
- Industry-grade safety guarantees for production apps.
🧱 Foundation for Custom Trackers
Introduced new foundational base classes for building your own tracking tools:
BaseTracker<T>— base for timestamp-aware persistent values with expiration handling.BaseCounterTracker— extension ofBaseTracker<int>with.increment()and consistent default logic.TrackerPeriod— an enum of aligned periods likeminutes10,hourly,daily,weekly, with.durationand.alignedStart().
v2.2.4
- Added factory methods:
Prf.json<T>(...)andPrf.enumerated<T>(...)PrfIso.json(...)andPrfIso.enumerated(...)
- Added
.isolatedgetter onPrf<T>for isolate-safe access. - Expanded native type support:
- Built-in adapters for
num,Uri,List<int>,List<bool>,List<double>,List<DateTime>now supported out of the box with allprfvalues! (with efficient binary encoding under the hood)
- Built-in adapters for
- All adapters are now
constfor reduced memory usage and better performance. - Updated README documentation.
- Now isolated
prfscan easily be created like this:
final isoValue = Prf<String>('username').isolated;Changes and Deprecations:
- Renamed
Prfy<T>→PrfIso<T>. - Added deprecation annotations with migration instructions.
- Deprecated classes (to be removed in v3.0.0):
PrfJson<T>→Prf.json<T>(...)PrfEnum<T>→Prf.enumerated<T>(...)Prfy<T>→PrfIso<T>PrfyJson<T>→PrfIso.json<T>(...)PrfyEnum<T>→PrfIso.enumerated<T>(...)- Or alternatively:
Prf.json<T>(...).isolated,Prf.enumerated<T>(...).isolated
- Added extensive tests for every single adapter, with more than 300 tests - all adapters are heavily tested to ensure data integrity.