{"id":21206203,"url":"https://github.com/rtmigo/prefnotifiers_flutter","last_synced_at":"2026-06-23T03:31:21.351Z","repository":{"id":54281218,"uuid":"341997829","full_name":"rtmigo/prefnotifiers_flutter","owner":"rtmigo","description":"🗃️ Flutter library representing shared preferences as ValueNotifier objects. Reads and writes occur asynchronously in background","archived":false,"fork":false,"pushed_at":"2023-09-23T02:59:21.000Z","size":186,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-19T11:42:05.622Z","etag":null,"topics":["changenotifier","flutter","shared-preferences","state-management"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/prefnotifiers","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rtmigo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-24T18:34:14.000Z","updated_at":"2024-01-28T14:19:21.000Z","dependencies_parsed_at":"2025-03-14T23:11:50.586Z","dependency_job_id":"790067bc-3f00-4d26-a7af-63624394e8bd","html_url":"https://github.com/rtmigo/prefnotifiers_flutter","commit_stats":null,"previous_names":["rtmigo/prefnotifiers"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/rtmigo/prefnotifiers_flutter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprefnotifiers_flutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprefnotifiers_flutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprefnotifiers_flutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprefnotifiers_flutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rtmigo","download_url":"https://codeload.github.com/rtmigo/prefnotifiers_flutter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rtmigo%2Fprefnotifiers_flutter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34674702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["changenotifier","flutter","shared-preferences","state-management"],"created_at":"2024-11-20T20:54:46.748Z","updated_at":"2026-06-23T03:31:21.336Z","avatar_url":"https://github.com/rtmigo.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Pub Package](https://img.shields.io/pub/v/prefnotifiers.svg)](https://pub.dev/packages/prefnotifiers)\n[![pub points](https://badges.bar/prefnotifiers/pub%20points)](https://pub.dev/packages/prefnotifiers/score)\n[![Actions Status](https://github.com/rtmigo/prefnotifiers.flutter/workflows/ci%20test/badge.svg?branch=master)](https://github.com/rtmigo/prefnotifiers.flutter/actions)\n\n# [prefnotifiers](https://github.com/rtmigo/prefnotifiers)\n\nThis library represents [shared_preferences](https://pub.dev/packages/shared_preferences) as `ValueNotifier` objects.\n\nIt fits in well with the paradigm of data models. Models make data readily available to widgets.\n\nReads and writes occur asynchronously in background.\n\n# Why use PrefNotifier?\n\nSuppose, we have parameter, that can be read with [shared_preferences](https://pub.dev/packages/shared_preferences) like that:\n\n``` dart\nfinal prefs = await SharedPreferences.getInstance();\nint myParamValue = await prefs.getInt(\"MyParameter\");\n```\n\nThere are two lines of problem:\n\n- This code is asynchronous. We cannot use such code directly when building a widget\n- The `paramValue` does not reflect the parameter changes\n\nInstead, we suggest using the new `PrefNotifier` class for accessing the parameter:\n\n``` dart\nfinal myParam = PrefNotifier\u003cint\u003e(\"MyParameter\");\n```\n\n- `myParam` object can be used as the only representation of `\"MyParameter\"` in the whole program\n- `myParam.value` allows indirectly read and write the shared preference value without getting out of sync\n- `Widget build(_)` methods can access value without relying on `FutureBuilder`\n- `myParam.addListener` makes it possible to track changes of the value\n\n# What is PrefNotifier?\n\n\n\n`PrefNotifier.value` provides **the best value we have for the moment**. The actual read/write operations happen asynchronously in background.\n\n`PrefNotifier` serves as a **model** for an individual parameter stored in shared preferences.\n\n## Types\n\nType                         | Аlternative to SharedPreferences'\n-----------------------------|---------------------------------------\n`PrefNotifier\u003cbool\u003e`         | `.setBool` `.getBool` `.remove`\n`PrefNotifier\u003cint\u003e`          | `.setInt` `.getInt` `.remove`\n`PrefNotifier\u003cdouble\u003e`       | `.setDouble` `.getDouble` `.remove`\n`PrefNotifier\u003cString\u003e`       | `.setString` `.getString` `.remove`\n`PrefNotifier\u003cList\u003cString\u003e\u003e` | `.setStringList` `.getStringList` `.remove`\n\n## Basic operations\n\nPrefNotifier | SharedPreferences\n--------------------------------|-----------------------------------------------\n`myParam = PrefNotifier\u003cint\u003e('MyParameter')` | `prefs = await SharedPreferences.getInstance()`\n`myParam.value = 42`              | `await prefs.setInt('MyParameter', 42)`\n`int? x = myParam.value`       | `int? x = await prefs.getInt('MyParameter')`\n`myParam.value = null`         | `await prefs.remove('MyParameter')`\n\nBut the most great is:\n\n``` dart\nmyParam.addListener(() =\u003e print('Value changed! New value: ${myParam.value}');\n```\n\n# How to use PrefNotifier?\n\n## Create \n\n``` dart\nfinal myParam = PrefNotifier\u003cint\u003e(\"MyParameter\");\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eBefore 1.0.0 and sound null safety it's PrefItem\u003c/summary\u003e\n\n``` dart\nfinal myParam = PrefItem\u003cint\u003e(SharedPrefsStorage(), \"MyParameter\");\n```\n\nIn newer version of the library `PrefItem` works as well. `PrefNotifier` is an easier to use alias.   \n\n\u003c/details\u003e\n\n\n## Read \n\nReading is is not finished yet. But we already can access `myParam.value`. By default, it returns `null`.\nWe can use it in synchronous code:\n\n``` dart\nWidget build(BuildContext context) {\n    if (myParam.value==null)\n        return Text(\"Not initialized yet\");\n    else\n        return Text(\"Value is ${myParam.value}\");\n}\n```\n\nSince `PrefNotifier` inherits from the `ValueListenable`, we can automatically \nrebuild the widget when the new value of `myParam` will be available:\n\n``` dart\nWidget build(BuildContext context) {\n    return ValueListenableBuilder(\n        valueListenable: myParam,\n        builder: (BuildContext context, int? value, Widget child) {\n            if (value==null)\n                return Text(\"Not initialized yet\");\n            else\n                return Text(\"Value is $value\");\n        });\n}\n```\n\n## Write \n\nThe code above will also rebuild the widget when value is changed. Let's change the value in a button callback:\n\n``` dart\nonTap: () {\n    // myParam.value is 3, shared preferences value is 3\n\n    myParam.value += 1;\n    myParam.value += 1;\n\n    // myParam.value is already changed to 5\n    //\n    // The widget will rebuild momentarily (i.e. on the next frame)\n    //\n    // Shared preferences still contain value 3. But asynchronous writing\n    // already started. It will rewrite value in a few milliseconds\n}\n```\n\n## Load\n\nFor a newly created `PrefNotifier` the `value` returns `null` until the object \nreads the actual data from the storage. Asynchronous **loading starts \nautomatically when the object is created**.\n \nBut what if we want to get the loaded data before doing anything else?\n\n``` dart\n\nfinal myParam = PrefNotifier\u003cint\u003e(\"TheParameter\");\nawait myParam.initialized;\n\n// we waited while the object was reading the data.\n// Now myParam.value returns the value from the storage, not default NULL.\n// Even if it is NULL, it is a NULL from the storage :)\n\n```\n\n## Keep in sync\n\nCreate a **single instance** of PrefNotifier for a **particular \nparameter**. Only access this parameter with this PrefNotifier instance.\n\n``` dart\nfinal myParam = PrefNotifier\u003cint\u003e(\"MyParameter\");\nmyParam.value = 5;\n\nawait (await SharedPreferences.getInstance())\n    .setInt(\"MyParameter\", 10); // DON'T DO THIS\n\nvar otherNotifier = PrefNotifier\u003cint\u003e(\"MyParameter\"); // DON'T DO THIS\notherNotifier = 20;\n\n// now the myParam.value is still 5.\n// And the myParam has no idea it is changed\n```\n\n## Test\n\nTo test a program that uses PrefNotifiers, you can populate initial values \nthe same way, as in the case of using SharedPreferences directly: \n\n``` dart \nTestWidgetsFlutterBinding.ensureInitialized();\nSharedPreferences.setMockInitialValues(Map\u003cString, dynamic\u003e values);\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frtmigo%2Fprefnotifiers_flutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frtmigo%2Fprefnotifiers_flutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frtmigo%2Fprefnotifiers_flutter/lists"}