{"id":32305331,"url":"https://github.com/futureware-tech/stream_with_value","last_synced_at":"2026-02-22T18:03:18.322Z","repository":{"id":38837698,"uuid":"343829336","full_name":"futureware-tech/stream_with_value","owner":"futureware-tech","description":null,"archived":false,"fork":false,"pushed_at":"2022-06-02T08:48:26.000Z","size":103,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-23T06:51:26.223Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/futureware-tech.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}},"created_at":"2021-03-02T15:56:34.000Z","updated_at":"2024-04-01T17:24:31.000Z","dependencies_parsed_at":"2022-08-26T19:51:16.708Z","dependency_job_id":null,"html_url":"https://github.com/futureware-tech/stream_with_value","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/futureware-tech/stream_with_value","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureware-tech%2Fstream_with_value","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureware-tech%2Fstream_with_value/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureware-tech%2Fstream_with_value/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureware-tech%2Fstream_with_value/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/futureware-tech","download_url":"https://codeload.github.com/futureware-tech/stream_with_value/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureware-tech%2Fstream_with_value/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29721056,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T15:10:41.462Z","status":"ssl_error","status_checked_at":"2026-02-22T15:10:04.636Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2025-10-23T06:49:58.746Z","updated_at":"2026-02-22T18:03:18.301Z","avatar_url":"https://github.com/futureware-tech.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stream_with_value\n\n[![pub package](https://img.shields.io/pub/v/stream_with_value.svg)](https://pub.dev/packages/stream_with_value)\n[![flutter build](https://github.com/futureware-tech/stream_with_value/workflows/flutter/badge.svg?branch=master\u0026event=push)](https://github.com/futureware-tech/stream_with_value/actions?query=workflow%3Aflutter+branch%3Amaster)\n[![code coverage](https://codecov.io/gh/futureware-tech/stream_with_value/branch/master/graph/badge.svg)](https://codecov.io/gh/futureware-tech/stream_with_value)\n\n## About\n\nIf you ever found yourself:\n\n- listening to a single-subscription\n  [Stream](https://api.dart.dev/stable/dart-async/Stream-class.html) and needing\n  to access the latest value on demand (and not just in the `listen` callback);\n- confused and tired of tedious handling of lazy-loaded values in\n  [StreamBuilder](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html),\n  especially handling the edge cases when the value is not loaded (progress\n  indicator);\n\nthen this package is for you. It provides an interface, which is an\nencapsulation of\n[Stream\u003cT\u003e](https://api.dart.dev/stable/dart-async/Stream-class.html) and a\nvalue of type `T`, along with a set of convenient implementations and\nextensions. The most common to use is a\n[StreamWithLatestValue](https://pub.dev/documentation/stream_with_value/latest/stream_with_value/StreamWithLatestValue-class.html),\nwhich automatically tracks the latest value emitted by the stream:\n\n```dart\n/// Abstract interface, the base of this package.\nabstract class StreamWithValue\u003cT\u003e {\n  /// The stream.\n  Stream\u003cT\u003e get updates;\n  /// The value.\n  T get value;\n  /// Whether the value is initialized.\n  bool get loaded;\n}\n\n/// A specific implementation which simply tracks the latest value emitted by\n/// the sourceStream.\nclass StreamWithLatestValue\u003cT\u003e implements StreamWithValue\u003cT\u003e {\n  StreamWithLatestValue(Stream\u003cT\u003e sourceStream) { /* ... */ }\n\n  factory StreamWithLatestValue.withInitialValue(\n    Stream\u003cT\u003e sourceStream, {\n    required T initialValue,\n  }) { /* ... */ }\n}\n```\n\nNote well: since subscribing to a single-subscription stream can be an expensive\noperation (e.g. it can initiate a network connection and start a download),\n[StreamWithLatestValue](https://pub.dev/documentation/stream_with_value/latest/stream_with_value/StreamWithLatestValue-class.html)\nwould not subscribe to the stream unless you do (e.g. through `updates.listen()`\nor passing it to\n[StreamBuilder](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html)).\nThis means that the `value` will not be `loaded` until a subscription is active\nand the first value is emitted by the stream.\n\nIf you want a different behavior, consider other implementations of\n`StreamWithValue` offered by this package, for example,\n[PushStreamWithValue](https://pub.dev/documentation/stream_with_value/latest/stream_with_value/PushStreamWithValue-class.html).\n\nThere's more to love about this package, see the\n[API reference](https://pub.dev/documentation/stream_with_value/latest/) for\nother helpers.\n\n### For Flutter users\n\nA very common pattern in reactive programming in Flutter is to show a progress\nindicator while an element of UI is loading (e.g. from remote database). Flutter\noffers convenient\n[StreamBuilder](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html),\nwhich allows you to customize behavior when a stream is not loaded, but you have\nto implement it from scratch and insert branching. And what if the value for\nthe stream has been loaded before, and the UI has just been rebuilt when user\nrotated the screen? This may cause flickering, and these two are exactly the\nproblems\n[StreamWithValue](https://pub.dev/documentation/stream_with_value/latest/stream_with_value/StreamWithValue-class.html)\nis here to solve. Use the convenience widgets:\n[StreamBuilderWithValue](https://pub.dev/documentation/stream_with_value/latest/stream_with_value/StreamBuilderWithValue-class.html)\nand if you don't want to handle `null` or not loaded data, then its friend,\n[DataStreamWithValueBuilder](https://pub.dev/documentation/stream_with_value/latest/stream_with_value/DataStreamWithValueBuilder-class.html)\nwill save your day.\n\n## How to use\n\nSee the [Install](https://pub.dev/packages/stream_with_value/install) section\non how to start using `StreamWithValue` in your project. You can use convenience\nwrappers to start improving your project right away:\n\n```dart\nStreamWithValue\u003cT\u003e _counter;\n\nvoid initState() {\n  _counter = StreamWithValue\u003cint\u003e(\n    Stream\u003cint\u003e.periodic(const Duration(seconds: 1))\n  );\n}\n\n// Before StreamWithValue, in the build() method:\nchild: StreamBuilder\u003cint\u003e(\n  stream: _counter.updates,\n  builder: (BuildContext context, AsyncSnapshot snapshot) {\n    return snapshot.hasData\n      ? Text(\n          '${snapshot.data}',\n          style: Theme.of(context).textTheme.headline4,\n        )\n      : CircularProgressIndicator();\n  },\n)\n\n// If you turn the screen, you will see a progress indicator for a moment. This\n// can be easily solved with StreamWithValue and StreamWithValueBuilder:\nchild: StreamBuilderWithValue\u003cint\u003e(\n  streamWithValue: _counter,\n  builder: (BuildContext context, AsyncSnapshot snapshot) {\n    return snapshot.hasData\n      ? Text(\n          '${snapshot.data}',\n          style: Theme.of(context).textTheme.headline4,\n        )\n      : CircularProgressIndicator();\n  },\n)\n\n/// Or use convenience widget in the code, which will automatically render a\n/// progress indicator if the value is not yet loaded:\nchild: DataStreamWithValueBuilder\u003cint\u003e(\n  streamWithValue: _counter,\n  builder: (BuildContext context, int value) =\u003e Text(\n      '${snapshot.data}',\n      style: Theme.of(context).textTheme.headline4,\n  ),\n)\n```\n\nSee more in the [Example](https://pub.dev/packages/stream_with_value/example)\nsection of the documentation. Happy streaming! Or building. Or both.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffutureware-tech%2Fstream_with_value","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffutureware-tech%2Fstream_with_value","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffutureware-tech%2Fstream_with_value/lists"}