{"id":17238334,"url":"https://github.com/hoc081098/stream_loader","last_synced_at":"2025-04-14T02:29:47.396Z","repository":{"id":36949044,"uuid":"233353474","full_name":"hoc081098/stream_loader","owner":"hoc081098","description":"🍂 A Flutter plugin for loading content asynchronously with Dart stream and RxDart. RxDart loader bloc. Reactive loader bloc. Simple reactive state management container - https://pub.dev/packages/stream_loader","archived":false,"fork":false,"pushed_at":"2024-09-17T23:02:18.000Z","size":331,"stargazers_count":3,"open_issues_count":16,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-09-18T03:29:56.684Z","etag":null,"topics":["bloc-architecture","bloc-pattern","bloc-pattern-rxdart","bloc-rxdart","flutter-bloc","flutter-bloc-pattern","flutter-bloc-pattern-rxdart","flutter-bloc-patterns","flutter-bloc-rxdart","flutter-bloc-sample","flutter-reactive","flutter-rx","flutter-rxbus","flutter-rxdart","flutter-stream","rxdart","rxdart-flutter","stream-loader"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/stream_loader","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/hoc081098.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":"2020-01-12T07:15:52.000Z","updated_at":"2023-05-30T08:22:50.000Z","dependencies_parsed_at":"2024-01-03T20:26:00.526Z","dependency_job_id":"b0437455-3d58-45e1-be8f-780a52f9e4c2","html_url":"https://github.com/hoc081098/stream_loader","commit_stats":{"total_commits":89,"total_committers":4,"mean_commits":22.25,"dds":0.0561797752808989,"last_synced_commit":"3566e39fcb3e7ce118fc6f1a149bc3889c609563"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoc081098%2Fstream_loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoc081098%2Fstream_loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoc081098%2Fstream_loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoc081098%2Fstream_loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hoc081098","download_url":"https://codeload.github.com/hoc081098/stream_loader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219845127,"owners_count":16556474,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["bloc-architecture","bloc-pattern","bloc-pattern-rxdart","bloc-rxdart","flutter-bloc","flutter-bloc-pattern","flutter-bloc-pattern-rxdart","flutter-bloc-patterns","flutter-bloc-rxdart","flutter-bloc-sample","flutter-reactive","flutter-rx","flutter-rxbus","flutter-rxdart","flutter-stream","rxdart","rxdart-flutter","stream-loader"],"created_at":"2024-10-15T05:45:16.597Z","updated_at":"2024-10-15T05:45:17.224Z","avatar_url":"https://github.com/hoc081098.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stream_loader ![alt text](https://avatars3.githubusercontent.com/u/6407041?s=32\u0026v=4)\n\n - A `Flutter` plugin for loading content asynchronously with `Dart Stream` and `RxDart`.\n - `RxDart` loader bloc.\n - Reactive loader bloc.\n - Simple reactive state management container.\n\n## Author: [Petrus Nguyễn Thái Học](https://github.com/hoc081098)\n\n[![Tests](https://github.com/hoc081098/stream_loader/actions/workflows/dart.yml/badge.svg)](https://github.com/hoc081098/stream_loader/actions/workflows/dart.yml)\n[![Build example](https://github.com/hoc081098/stream_loader/actions/workflows/build-example.yml/badge.svg)](https://github.com/hoc081098/stream_loader/actions/workflows/build-example.yml)\n[![Pub](https://img.shields.io/pub/v/stream_loader.svg)](https://pub.dartlang.org/packages/stream_loader)\n[![Build Status](https://travis-ci.org/hoc081098/stream_loader.svg?branch=master)](https://travis-ci.org/hoc081098/stream_loader)\n[![codecov](https://codecov.io/gh/hoc081098/stream_loader/branch/master/graph/badge.svg)](https://codecov.io/gh/hoc081098/stream_loader)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Getting Started\n\nIn your flutter project, add the dependency to your `pubspec.yaml`\n\n```yaml\ndependencies:\n  ...\n  stream_loader: \u003clatest_version\u003e\n```\n\n## Examples\n-   [stream_loader/example](https://github.com/hoc081098/stream_loader/tree/master/example)\n-   [stream_loader_demo](https://github.com/hoc081098/stream_loader_demo)\n\n## Usage\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/hoc081098/hoc081098.github.io/raw/master/stream_loader/untitled.gif\" height=\"480\"/\u003e\n\u003c/p\u003e\n\n#### 1. Model and api\n```dart\nabstract class Comment implements Built\u003cComment, CommentBuilder\u003e { ... }\n\nclass Api {\n  Stream\u003cBuiltList\u003cComment\u003e\u003e getComments() { ... }\n  Stream\u003cComment\u003e getCommentBy({@required int id}) { ... }\n}\nfinal api = Api();\n```\n\n#### 2. Create LoaderWidget load comments from api\n```dart\nimport 'package:stream_loader/stream_loader.dart';\n\nLoaderWidget\u003cBuiltList\u003cComment\u003e\u003e(\n  blocProvider: () =\u003e LoaderBloc(\n    loaderFunction: api.getComments,\n    refresherFunction: api.getComments,\n    initialContent: \u003cComment\u003e[].build(),\n    logger: print,\n  ),\n  messageHandler: (context, message, bloc) {\n    message.fold(\n      onFetchFailure: (error, stackTrace) =\u003e context.snackBar('Fetch error'),\n      onFetchSuccess: (_) {},\n      onRefreshSuccess: (data) =\u003e context.snackBar('Refresh success'),\n      onRefreshFailure: (error, stackTrace) =\u003e context.snackBar('Refresh error'),\n    );\n  },\n  builder: (context, state, bloc) {\n    if (state.error != null) {\n      return ErrorWidget(error: state.error);\n    }\n    if (state.isLoading) {\n      return LoadingWidget();\n    }\n    return RefreshIndicator(\n      onRefresh: bloc.refresh,\n      child: CommentsListWidget(comments: state.content),\n    );\n  }\n);\n```\n\n#### 3. Create LoaderWidget load comment detail from api\n```dart\nimport 'package:stream_loader/stream_loader.dart';\n\nfinal Comment comment;\nfinal loadDetail = () =\u003e api.getCommentBy(id: comment.id);\n\nLoaderWidget\u003cComment\u003e(\n  blocProvider: () =\u003e LoaderBloc(\n    loaderFunction: loadDetail,\n    refresherFunction: loadDetail,\n    initialContent: comment,\n    logger: print,\n  ),\n  messageHandler: (context, message, bloc) {\n    message.fold(\n      onFetchFailure: (_, __) {},\n      onFetchSuccess: (_) {},\n      onRefreshFailure: (_, __) {},\n      onRefreshSuccess: (_) =\u003e context.snackBar('Refresh success'),\n    );\n  },\n  builder: (context, state, bloc) {\n    return RefreshIndicator(\n      onRefresh: bloc.refresh,\n      child: CommentDetailWidget(comment: state.content),\n    );\n  },\n);\n```\n\n#### Note: Can use `LoaderBloc` without `LoaderWidget` easily\n```dart\n\nclass _CommentsState extends State\u003cComments\u003e {\n  LoaderBloc\u003cBuiltList\u003cComment\u003e\u003e bloc;\n\n  @override\n  void didChangeDependencies() {\n    super.didChangeDependencies();\n\n    bloc ??= LoaderBloc(\n      loaderFunction: api.getComments,\n      refresherFunction: api.getComments,\n      initialContent: \u003cComment\u003e[].build(),\n      logger: print,\n    )..fetch();\n  }\n\n  @override\n  void dispose() {\n    bloc.dispose();\n    super.dispose();\n  }\n  \n  @override\n  Widget build(BuildContext context) {\n    return StreamBuilder\u003cLoaderState\u003cBuiltList\u003cComment\u003e\u003e\u003e(\n      stream: bloc.state$,\n      initialData: bloc.state$.value, // \u003c- required because bloc.state$ does not replay the latest value\n      builder: (context, snapshot) {\n        final state = snapshot.data;\n        \n        if (state.error != null) {\n          return ErrorWidget(error: state.error);\n        }\n        if (state.isLoading) {\n          return LoadingWidget();\n        }\n        return RefreshIndicator(\n          onRefresh: bloc.refresh,\n          child: CommentsListWidget(comments: state.content),\n        );\n      }\n    );\n  }\n}\n```\n\n### Change _flatten behavior_ of `loaderFunction` and `refresherFunction`.\n\n-   Default behavior of `loaderFunction` is `FlattenStrategy.latest` (uses `switchMap`).\n-   Default behavior of `refreshFlatMapPolicy` is `FlattenStrategy.first`, (uses `exhaustMap`).\n-   To change them, passing your value to `LoaderBloc` constructor\n\n```dart\nLoaderBloc(\n  ...,\n  loaderFlattenStrategy: FlattenStrategy.concat, // asyncExpand\n  refreshFlattenStrategy: FlattenStrategy.latest, // switchMap\n);\n```\n\n## License\n    MIT License\n    \n    Copyright (c) 2020-2022 Petrus Nguyễn Thái Học\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoc081098%2Fstream_loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoc081098%2Fstream_loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoc081098%2Fstream_loader/lists"}