Repository: alibaba/fish-redux
Branch: master
Commit: 40b853bfa084
Files: 314
Total size: 554.9 KB
Directory structure:
gitextract_al9_2a3r/
├── .github/
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ ├── custom.md
│ └── feature_request.md
├── .gitignore
├── .metadata
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── doc/
│ ├── README-cn.md
│ ├── README.md
│ ├── concept/
│ │ ├── action-cn.md
│ │ ├── action.md
│ │ ├── adapter-cn.md
│ │ ├── adapter.md
│ │ ├── auto-dispose-cn.md
│ │ ├── auto-dispose.md
│ │ ├── component-cn.md
│ │ ├── component.md
│ │ ├── connector-cn.md
│ │ ├── connector.md
│ │ ├── custom-adapter-cn.md
│ │ ├── custom-adapter.md
│ │ ├── dependencies-cn.md
│ │ ├── dependencies.md
│ │ ├── dependent-cn.md
│ │ ├── dependent.md
│ │ ├── directory-cn.md
│ │ ├── directory.md
│ │ ├── dynamic-flow-adapter-cn.md
│ │ ├── dynamic-flow-adapter.md
│ │ ├── effect-cn.md
│ │ ├── effect.md
│ │ ├── evolution-of-fish-redux.md
│ │ ├── features.md
│ │ ├── filter-cn.md
│ │ ├── filter.md
│ │ ├── higher-effect-cn.md
│ │ ├── higher-effect.md
│ │ ├── lifecycle-cn.md
│ │ ├── lifecycle.md
│ │ ├── mechanism-cn.md
│ │ ├── mechanism.md
│ │ ├── middleware-cn.md
│ │ ├── middleware.md
│ │ ├── on-error-cn.md
│ │ ├── on-error.md
│ │ ├── oop-cn.md
│ │ ├── oop.md
│ │ ├── page-cn.md
│ │ ├── page.md
│ │ ├── reducer-cn.md
│ │ ├── reducer.md
│ │ ├── redux-cn.md
│ │ ├── redux.md
│ │ ├── should-update-cn.md
│ │ ├── should-update.md
│ │ ├── static-flow-adapter-cn.md
│ │ ├── static-flow-adapter.md
│ │ ├── view-cn.md
│ │ ├── view.md
│ │ ├── what's-adapter.md
│ │ ├── what's-connector.md
│ │ ├── what's-the-diiference-cn.md
│ │ ├── what's-the-diiference.md
│ │ ├── widget-wrapper-cn.md
│ │ └── widget-wrapper.md
│ └── introduction/
│ ├── README-cn.md
│ └── README.md
├── docs/
│ ├── .nojekyll
│ ├── README.md
│ ├── _navbar.md
│ ├── _sidebar.md
│ ├── concept/
│ │ ├── _navbar.md
│ │ ├── _sidebar.md
│ │ ├── action.md
│ │ ├── adapter.md
│ │ ├── auto-dispose.md
│ │ ├── component.md
│ │ ├── connector.md
│ │ ├── custom-adapter.md
│ │ ├── dependencies.md
│ │ ├── dependent.md
│ │ ├── directory.md
│ │ ├── dynamic-flow-adapter.md
│ │ ├── effect.md
│ │ ├── evolution-of-fish-redux.md
│ │ ├── features.md
│ │ ├── filter.md
│ │ ├── higher-effect.md
│ │ ├── lifecycle.md
│ │ ├── mechanism.md
│ │ ├── middleware-cn.md
│ │ ├── middleware.md
│ │ ├── on-error.md
│ │ ├── oop.md
│ │ ├── page.md
│ │ ├── reducer.md
│ │ ├── redux.md
│ │ ├── should-update.md
│ │ ├── static-flow-adapter.md
│ │ ├── view.md
│ │ ├── what's-adapter.md
│ │ ├── what's-connector.md
│ │ ├── what's-the-diiference.md
│ │ └── widget-wrapper.md
│ ├── index.html
│ └── zh-cn/
│ ├── README.md
│ ├── _sidebar.md
│ └── concept/
│ ├── _navbar.md
│ ├── _sidebar.md
│ ├── action.md
│ ├── adapter.md
│ ├── auto-dispose.md
│ ├── component.md
│ ├── connector.md
│ ├── custom-adapter.md
│ ├── dependencies.md
│ ├── dependent.md
│ ├── directory.md
│ ├── dynamic-flow-adapter.md
│ ├── effect.md
│ ├── filter.md
│ ├── higher-effect.md
│ ├── lifecycle.md
│ ├── mechanism.md
│ ├── middleware.md
│ ├── on-error.md
│ ├── oop.md
│ ├── page.md
│ ├── reducer.md
│ ├── redux.md
│ ├── should-update.md
│ ├── static-flow-adapter.md
│ ├── view.md
│ ├── what's-adapter.md
│ ├── what's-connector.md
│ ├── what's-the-diiference.md
│ └── widget-wrapper.md
├── example/
│ ├── .flutter-plugins-dependencies
│ ├── .gitignore
│ ├── .metadata
│ ├── README.md
│ ├── lib/
│ │ ├── app.dart
│ │ ├── global_store/
│ │ │ ├── action.dart
│ │ │ ├── reducer.dart
│ │ │ ├── state.dart
│ │ │ └── store.dart
│ │ ├── main.dart
│ │ ├── todo_edit_page/
│ │ │ ├── action.dart
│ │ │ ├── effect.dart
│ │ │ ├── page.dart
│ │ │ ├── state.dart
│ │ │ └── view.dart
│ │ └── todo_list_page/
│ │ ├── action.dart
│ │ ├── effect.dart
│ │ ├── flow_adapter/
│ │ │ ├── adapter.dart
│ │ │ ├── connector.dart
│ │ │ └── reducer.dart
│ │ ├── list_adapter/
│ │ │ ├── action.dart
│ │ │ ├── adapter.dart
│ │ │ └── reducer.dart
│ │ ├── page.dart
│ │ ├── reducer.dart
│ │ ├── report_component/
│ │ │ ├── component.dart
│ │ │ ├── state.dart
│ │ │ └── view.dart
│ │ ├── state.dart
│ │ ├── todo_component/
│ │ │ ├── action.dart
│ │ │ ├── component.dart
│ │ │ ├── effect.dart
│ │ │ ├── reducer.dart
│ │ │ ├── state.dart
│ │ │ └── view.dart
│ │ └── view.dart
│ ├── pubspec.yaml
│ ├── test/
│ │ └── widget_test.dart
│ └── web/
│ ├── index.html
│ └── manifest.json
├── fish_redux.iml
├── lib/
│ ├── fish_redux.dart
│ └── src/
│ ├── extensions/
│ │ ├── adapter_extensions.dart
│ │ ├── component_extensions.dart
│ │ ├── connector_extensions.dart
│ │ └── extendsions.dart
│ ├── redux/
│ │ ├── apply_middleware.dart
│ │ ├── basic.dart
│ │ ├── combine_reducers.dart
│ │ ├── connector.dart
│ │ ├── create_store.dart
│ │ └── redux.dart
│ ├── redux_adapter/
│ │ ├── adapter.dart
│ │ ├── dynamic_flow_adapter.dart
│ │ ├── flow_adapter.dart
│ │ ├── recycle_context.dart
│ │ ├── redux_adapter.dart
│ │ ├── source_flow_adapter.dart
│ │ └── static_flow_adapter.dart
│ ├── redux_aop/
│ │ ├── aop.dart
│ │ ├── common_aop/
│ │ │ ├── common_aop.dart
│ │ │ ├── debounce.dart
│ │ │ ├── debug.dart
│ │ │ ├── delay.dart
│ │ │ ├── log.dart
│ │ │ ├── memoize.dart
│ │ │ ├── performance.dart
│ │ │ ├── throttle.dart
│ │ │ └── wait_until.dart
│ │ └── redux_aop.dart
│ ├── redux_component/
│ │ ├── auto_dispose.dart
│ │ ├── basic.dart
│ │ ├── batch_store.dart
│ │ ├── component.dart
│ │ ├── context.dart
│ │ ├── dependencies.dart
│ │ ├── dependent.dart
│ │ ├── dispatch_bus.dart
│ │ ├── enhancer.dart
│ │ ├── helper.dart
│ │ ├── lifecycle.dart
│ │ ├── local.dart
│ │ ├── logic.dart
│ │ ├── page.dart
│ │ └── redux_component.dart
│ ├── redux_component_mixin/
│ │ ├── keep_alive_mixin.dart
│ │ ├── private_reducer_mixin.dart
│ │ ├── redux_component_mixin.dart
│ │ ├── single_ticker_provider_mixin.dart
│ │ ├── ticker_provider_mixin.dart
│ │ ├── visible_change_mixin.dart
│ │ └── widgets_binding_observer_mixin.dart
│ ├── redux_connector/
│ │ ├── connector.dart
│ │ ├── generator.dart
│ │ ├── helper.dart
│ │ ├── map_like.dart
│ │ ├── none.dart
│ │ ├── op_mixin.dart
│ │ ├── redux_connector.dart
│ │ └── reselect.dart
│ ├── redux_middleware/
│ │ ├── adapter_middleware/
│ │ │ ├── adapter_middleware.dart
│ │ │ └── safety_adapter.dart
│ │ ├── middleware/
│ │ │ ├── log.dart
│ │ │ ├── middleware.dart
│ │ │ └── performance.dart
│ │ ├── redux_middleware.dart
│ │ └── view_middleware/
│ │ ├── safety_view.dart
│ │ └── view_middleware.dart
│ ├── redux_routes/
│ │ ├── page_routes.dart
│ │ └── redux_routes.dart
│ └── utils/
│ ├── collections.dart
│ ├── debug.dart
│ ├── hash.dart
│ ├── tuple.dart
│ └── utils.dart
├── pubspec.yaml
└── test/
├── lib/
│ ├── all_test.dart
│ ├── instrument.dart
│ ├── redux/
│ │ ├── redux_test.dart
│ │ └── store_test.dart
│ ├── redux_adapter/
│ │ ├── adapter_test.dart
│ │ ├── dynamic_adapter_test.dart
│ │ ├── redux_adapter_test.dart
│ │ ├── source_adapter_test.dart
│ │ └── static_flow_adapter_test.dart
│ ├── redux_aop/
│ │ ├── memoize_test.dart
│ │ └── redux_aop_test.dart
│ ├── redux_component/
│ │ ├── auto_dispose_test.dart
│ │ ├── component_test.dart
│ │ ├── lifecycle_test.dart
│ │ ├── page_test.dart
│ │ └── redux_component_test.dart
│ ├── redux_connector/
│ │ ├── map_like_test.dart
│ │ ├── redux_connector_test.dart
│ │ └── reselect_test.dart
│ ├── redux_middleware/
│ │ └── redux_middleware_test.dart
│ ├── redux_routes/
│ │ └── redux_routes_test.dart
│ ├── track.dart
│ └── utils/
│ ├── collections_test.dart
│ └── utils_test.dart
├── pubspec.yaml
└── test_widgets/
├── .gitignore
├── lib/
│ ├── adapter/
│ │ ├── action.dart
│ │ ├── adapter.dart
│ │ ├── page.dart
│ │ └── state.dart
│ ├── component/
│ │ ├── action.dart
│ │ ├── component.dart
│ │ ├── page.dart
│ │ └── state.dart
│ ├── dynamic_flow_adapter/
│ │ ├── action.dart
│ │ ├── adapter.dart
│ │ ├── component.dart
│ │ ├── dynamic_flow_adapter.dart
│ │ ├── page.dart
│ │ └── state.dart
│ ├── main.dart
│ ├── page/
│ │ ├── action.dart
│ │ ├── exception.dart
│ │ ├── page.dart
│ │ └── state.dart
│ ├── source_flow_adapter/
│ │ ├── action.dart
│ │ ├── adapter.dart
│ │ ├── component.dart
│ │ ├── page.dart
│ │ ├── source_flow_adapter.dart
│ │ └── state.dart
│ ├── static_flow_adapter/
│ │ ├── action.dart
│ │ ├── component.dart
│ │ ├── page.dart
│ │ ├── state.dart
│ │ └── static_flow_adapter.dart
│ └── test_base.dart
└── pubspec.yaml
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
Show the code you wrote as completely as possible.
```dart
/// your code here
```
**To Reproduce**
Steps to reproduce the behavior.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Additional context**
1. The version of fish-redux which you are using.
2. The information from flutter doctor.
================================================
FILE: .github/ISSUE_TEMPLATE/custom.md
================================================
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .gitignore
================================================
.DS_Store
.atom/
.idea/
.vscode/
.packages
.pub/
.dart_tool/
build/
pubspec.lock
android/
ios/
.gradle/
build.gradle
gradle/
gradlew
gradlew.bat
local.properties
redux.iml
pubspec.lock
android/local.properties
# docs
node_modules/
================================================
FILE: .metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
channel: stable
project_type: package
================================================
FILE: .travis.yml
================================================
os:
- linux
sudo: false
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- libstdc++6
# - fonts-droid
before_script:
- git clone https://github.com/flutter/flutter.git -b stable --depth 1
- ./flutter/bin/flutter doctor
script:
- ./flutter/bin/flutter test --coverage --coverage-path=lcov.info
after_success:
- bash <(curl -s https://codecov.io/bash)
cache:
directories:
- $HOME/.pub-cache
================================================
FILE: CHANGELOG.md
================================================
## [0.3.7]
- fix test .
- revert issue 613
## [0.3.6]
- fix some dos .
## [0.3.5]
- fix deprecated using of api - inheritFromWidgetOfExactType .
## [0.3.4]
- fix PureViewComponent's dispatch bug
## [0.3.3]
- fix Page name duplication
- easy to use reselect
- add keep-alive-client wrapper
- fix spell error on pure-view-widget
- add default widget for component.buildComponent api
- add docsify to view docs
- add unit test for collection utils and maplike connector
## [0.3.2]
- fix Page name duplication
## [0.3.1]
- rename AdapterSource’s api
- add PureViewComponent
- deprecate broadcastEffect
-
## [0.3.0]
- add SourceFlowAdapter
- Use SourceFlowAdapter instead of DynamicFlowAdapter in example
- deprecate DynamicFlowAdapter
## [0.2.8]
- fix item-bean clone bug #493
## [0.2.7]
- add StateKey #461
- reselect optimization #482
## [0.2.6]
- add TickerProviderMixin
- let dispatch return whatever result in effect. #462
- fix Reselect's _listEquals bug #457
- fix SingleTickerProviderMixin & TickerProviderMixin’s dispose bug #461
- add ClearOnDependenciesChanged
## [0.2.5]
- add ctx.listen api
- rename LocalState to LocalProps
- correct some comments
## [0.2.4]
- fix Context.broadcast bug #375
- fix PrivateReducerMixin bug #380
- add LocalState
## [0.2.3]
- Reconstruct Context
- Breaking-change
- Reconstruct dependencies
- Remove OOP style
- Remove higherEffect
- Remove deprecated api(Connector, createMixedStore, AutoDispose:follow, AutoDispose:follower)
- Remove unused DisposedException
- Hide widgets.dart's Action to compate with flutter1.7
- Compate with flutter_web
## [0.2.2]
- add congruent conn
- fields mainCtx & viewUpdater in ComponentState become public
- fix bug when a store recived action after teardown
## [0.2.1]
- add forceUpdate api on context
- fix bug in adapter’s appear & disappear if items are recycled
- fix bug in connectStores api if page has no reducer
## [0.2.0]
- force update if driven by outside observable
- fix inverter bugs & optimization connectStores api
- modify the use of global state in example
## [0.1.9]
- add mixed-store's batch notification feature
## [0.1.8]
- add api to subscribe app-store for page-store
- add api to subscribe app-store for component
- add viewMiddleware
- add adapterMiddleware
- add effectMiddleware
- add protected attribute method, more friendly to OOP
- remove debug_report
## [0.1.7]
- reconstruct mixed-store
- reconstruct communication
- rename appBroadcast to broadcast
- rename pageBroadcast to broadcastEffect
- add dispatch-bus
- enhance dispatch-api
- add some docs
- move test to dev_dependencies
## [0.1.6]
- fix bug if component has no reducer in app-routes
- reconstruct createStore
- app-routes's store to be visible
## [0.1.5]
- fix bug if notified on building
- reconstruct test
- add mergeMiddleware\$
## [0.1.4]
- add support for AppStore
- add routes
- move middleware/aop to the top dir
- add PrivateReducerMixin
- add reselect
- add docs
## [0.1.3]
- add support for immutable-state #111
- fix the same type of state component reuse in listview #107
- remove warnings in logMiddleware for debug-actions #98
- correct spelling
- modify bindAction #73
## [0.1.2]
- add stfState field in Context #58
- add batchedNotify feature in page-store
- add some docs
- correct spelling
## [0.1.1]
- fix hot-reload bug
- add excluedSelf in broadcast
- rename sample to example
- rename docs to doc
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Alibaba, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
Fish Redux
[](https://travis-ci.org/alibaba/fish-redux) [](https://pub.dartlang.org/packages/fish_redux) [](https://codecov.io/gh/alibaba/fish-redux)
## What is Fish Redux ?
Fish Redux is an assembled flutter application framework based on Redux state management.
It is suitable for building medium and large applications.
It has four characteristics:
> 1. Functional Programming
> 2. Predictable state container
> 3. Pluggable componentization
> 4. Non-destructive performance
## Architecture diagram
## Installation
[Go](https://pub.dartlang.org/packages/fish_redux#-installing-tab-)
## Documentation
Language: [English](doc/README.md) | [中文简体](doc/README-cn.md)
## Examples
- [todo list](example) - a simple todo list demo.
- run it:
```
cd ./example
flutter create .
flutter run
```
## What's the difference between 'Fish Redux' and 'Redux' ?
- [answers](doc/concept/what's-the-diiference.md)
## Plugins
### Code Template
- [Fish Redux Template For Android Studio](https://github.com/BakerJQ/FishReduxTemplateForAS), by BakerJQ.
- [Fish Redux Template For VSCode](https://github.com/huangjianke/fish-redux-template), by huangjianke.
### Dev-Tools
- Redux Inspector (using [Flutter Debugger](https://github.com/blankapp/flutter-debugger) and [flipperkit_fish_redux_middleware](https://pub.dartlang.org/packages/flipperkit_fish_redux_middleware)) for Fish Redux apps, by [JianyingLi](https://github.com/lijy91)
## License
- Fish Redux is released under the Apache 2.0 license. See [LICENSE](LICENSE) for details.
## 关于我们
阿里巴巴-闲鱼技术是国内最早也是最大规模线上运行Flutter的团队。
我们在公众号中为你精选了Flutter独家干货,全面而深入。
内容包括:Flutter的接入、规模化应用、引擎探秘、工程体系、创新技术等教程和开源信息。
**架构/服务端/客户端/前端/质量工程师 在公众号中投递简历,名额不限哦**
欢迎来闲鱼做一个好奇、幸福、有影响力的程序员,简历投递:tino.wjf@alibaba-inc.com
订阅地址
[For English](https://twitter.com/xianyutech "For English")
================================================
FILE: analysis_options.yaml
================================================
# Specify analysis options.
#
# Until there are meta linter rules, each desired lint must be explicitly enabled.
# See: https://github.com/dart-lang/linter/issues/288
#
# For a list of lints, see: http://dart-lang.github.io/linter/lints/
# See the configuration guide for more
# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer
#
# There are four similar analysis options files in the flutter repos:
# - analysis_options.yaml (this file)
# - packages/flutter/lib/analysis_options_user.yaml
# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml
# - https://github.com/flutter/engine/blob/master/analysis_options.yaml
#
# This file contains the analysis options used by Flutter tools, such as IntelliJ,
# Android Studio, and the `flutter analyze` command.
#
# The flutter/plugins repo contains a copy of this file, which should be kept
# in sync with this file.
analyzer:
language:
enableSuperMixins: true
strong-mode:
implicit-dynamic: false
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
# allow having TODOs in the code
todo: ignore
exclude:
- 'bin/cache/**'
- 'flutter/**'
# the following two are relative to the stocks example and the flutter package respectively
# see https://github.com/dart-lang/sdk/issues/28463
- 'lib/i18n/stock_messages_*.dart'
- 'lib/src/http/**'
linter:
rules:
# these rules are documented on and in the same order as
# the Dart Lint rules page to make maintenance easier
# https://github.com/dart-lang/linter/blob/master/example/all.yaml
- always_declare_return_types
- always_put_control_body_on_new_line
# - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
- always_require_non_null_named_parameters
- always_specify_types
- annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
- avoid_as
# - avoid_bool_literals_in_conditional_expressions # not yet tested
# - avoid_catches_without_on_clauses # we do this commonly
# - avoid_catching_errors # we do this commonly
- avoid_classes_with_only_static_members
- avoid_empty_else
- avoid_function_literals_in_foreach_calls
- avoid_init_to_null
- avoid_null_checks_in_equality_operators
# - avoid_positional_boolean_parameters # not yet tested
# - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
- avoid_relative_lib_imports
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
# - avoid_returning_null # we do this commonly
# - avoid_returning_this # https://github.com/dart-lang/linter/issues/842
# - avoid_setters_without_getters # not yet tested
# - avoid_single_cascade_in_expression_statements # not yet tested
- avoid_slow_async_io
# - avoid_types_as_parameter_names # https://github.com/dart-lang/linter/pull/954/files
# - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unused_constructor_parameters # https://github.com/dart-lang/linter/pull/847
- await_only_futures
- camel_case_types
- cancel_subscriptions
# - cascade_invocations # not yet tested
# - close_sinks # https://github.com/flutter/flutter/issues/5789
# - comment_references # blocked on https://github.com/dart-lang/dartdoc/issues/1153
# - constant_identifier_names # https://github.com/dart-lang/linter/issues/204
- control_flow_in_finally
- directives_ordering
- empty_catches
- empty_constructor_bodies
- empty_statements
- hash_and_equals
- implementation_imports
# - invariant_booleans # https://github.com/flutter/flutter/issues/5790
- iterable_contains_unrelated_type
# - join_return_with_assignment # not yet tested
- library_names
- library_prefixes
- list_remove_unrelated_type
# - literal_only_boolean_expressions # https://github.com/flutter/flutter/issues/5791
- no_adjacent_strings_in_list
- no_duplicate_case_values
- non_constant_identifier_names
# - omit_local_variable_types # opposite of always_specify_types
# - one_member_abstracts # too many false positives
# - only_throw_errors # https://github.com/flutter/flutter/issues/5792
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
# - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_bool_in_asserts
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
# - prefer_constructors_over_static_methods # not yet tested
- prefer_contains
# - prefer_equal_for_default_values # not yet tested
# - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
- prefer_final_fields
- prefer_final_locals
- prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested
- prefer_initializing_formals
# - prefer_interpolation_to_compose_strings # not yet tested
- prefer_is_empty
- prefer_is_not_empty
- prefer_single_quotes
- prefer_typing_uninitialized_variables
- recursive_getters
- slash_for_doc_comments
# - sort_constructors_first
- sort_unnamed_constructors_first
- super_goes_last
- test_types_in_equals
- throw_in_finally
# - type_annotate_public_apis # subset of always_specify_types
- type_init_formals
# - unawaited_futures # https://github.com/flutter/flutter/issues/5793
- unnecessary_brace_in_string_interps
- unnecessary_getters_setters
# - unnecessary_lambdas # https://github.com/dart-lang/linter/issues/498
- unnecessary_null_aware_assignments
- unnecessary_null_in_if_null_operators
- unnecessary_overrides
# - unnecessary_parenthesis
# - unnecessary_statements # not yet tested
- unnecessary_this
- unnecessary_new
- unnecessary_const
- unrelated_type_equality_checks
- use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested
# - use_string_buffers # https://github.com/dart-lang/linter/pull/664
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
- valid_regexps
================================================
FILE: doc/README-cn.md
================================================
- **简介**
- [关于](introduction/README-cn.md)
- [演进](concept/evolution-of-fish-redux.md)
- [特性](concept/features.md)
- **核心概念**
- [Redux](concept/redux-cn.md)
- [Action](concept/action-cn.md)
- [Connector](concept/connector-cn.md)
- [Reducer](concept/reducer-cn.md)
- [Middleware](concept/middleware-cn.md)
- [Component](concept/component-cn.md)
- [View](concept/view-cn.md)
- [Reducer](concept/reducer-cn.md)
- [Effect](concept/effect-cn.md)
- [HigherEffect](concept/higher-effect-cn.md)
- [Lifecycle](concept/lifecycle-cn.md)
- [Dependencies](concept/dependencies-cn.md)
- [Dependent](concept/dependent-cn.md)
- [ShouldUpdate](concept/should-update-cn.md)
- [OnError](concept/on-error-cn.md)
- [Filter](concept/filter-cn.md)
- [OOP](concept/oop-cn.md)
- [WidgetWrapper](concept/widget-wrapper-cn.md)
- [Page](concept/page-cn.md)
- [Adapter](concept/adapter-cn.md)
- [StaticFlowAdapter](concept/static-flow-adapter-cn.md)
- [DynamicFlowAdapter](concept/dynamic-flow-adapter-cn.md)
- [CustomAdapter](concept/custom-adapter-cn.md)
- **其他**
- [What's the difference between 'Fish Redux' and 'Redux' ?](concept/what's-the-diiference-cn.md)
- [What's-adapter](concept/what's-adapter.md)
- [What's-connector](concept/what's-connector.md)
- [Mechanism](concept/mechanism-cn.md)
- [Directory](concept/directory-cn.md)
================================================
FILE: doc/README.md
================================================
- **Introduction**
- [About](introduction/README.md)
- [Evolution](concept/evolution-of-fish-redux.md)
- [Features](concept/features.md)
- **Core Concepts**
- [Redux](concept/redux.md)
- [Action](concept/action.md)
- [Connector](concept/connector.md)
- [Reducer](concept/reducer.md)
- [Middleware](concept/middleware.md)
- [Component](concept/component.md)
- [View](concept/view.md)
- [Reducer](concept/reducer.md)
- [Effect](concept/effect.md)
- [HigherEffect](concept/higher-effect.md)
- [Lifecycle](concept/lifecycle.md)
- [Dependencies](concept/dependencies.md)
- [Dependent](concept/dependent.md)
- [ShouldUpdate](concept/should-update.md)
- [OnError](concept/on-error.md)
- [Filter](concept/filter.md)
- [OOP](concept/oop.md)
- [WidgetWrapper](concept/widget-wrapper.md)
- [Page](concept/page.md)
- [Adapter](concept/adapter.md)
- [StaticFlowAdapter](concept/static-flow-adapter.md)
- [DynamicFlowAdapter](concept/dynamic-flow-adapter.md)
- [CustomAdapter](concept/custom-adapter.md)
- **Others**
- [What's the difference between 'Fish Redux' and 'Redux' ?](concept/what's-the-diiference.md)
- [What is an adapter?](concept/what's-adapter.md)
- [What is a connector?](concept/what's-connector.md)
- [Communication mechanism of fish-redux](concept/mechanism.md)
- [Recommended directory structure](concept/directory.md)
================================================
FILE: doc/concept/action-cn.md
================================================
# Action
- Action 包含两个字段
- type
- payload
- 推荐的写法是
- 为一个组件|适配器创建一个 action.dart 文件,包含两个类
- 为 type 字段起一个枚举类
- 为 Action 的创建起一个 ActionCreator 类,这样利于约束 payload 的类型。
- Effect 接受处理的 Action,以 on{Verb} 命名
- Reducer 接受处理的 Action,以{verb} 命名
- 示例代码
```dart
enum MessageAction {
onShare,
shared,
}
class MessageActionCreator {
static Action onShare(Map payload) {
return Action(MessageAction.onShare, payload: payload);
}
static Action shared() {
return const Action(MessageAction.shared);
}
}
```
================================================
FILE: doc/concept/action.md
================================================
# Action
- Action contains two fields
- type
- payload
- Recommended way of writing action
- Create an action.dart file for a component|adapter that contains two classes
- An enumeration class for the type field
- An ActionCreator class is created for the creator of the Action, which helps to constrain the type of payload.
- Effect Accepted Action which's type is named after `on{verb}`
- Reducer Accepted Action which's type is named after `{verb}`
- Sample code
```dart
enum MessageAction {
onShare,
shared,
}
class MessageActionCreator {
static Action onShare(Map payload) {
return Action(MessageAction.onShare, payload: payload);
}
static Action shared() {
return const Action(MessageAction.shared);
}
}
```
================================================
FILE: doc/concept/adapter-cn.md
================================================
# Adapter
- 我们在基础 Component 的概念外,额外增加了一种组件化的抽象 Adapter。它的目标是解决 Component 模型在 ListView 的场景下的 3 个问题
- 1)将一个"Big-Cell"放在 ListView 里,无法享受 ListView 代码的性能优化。
- 2)Component 无法区分 appear|disappear 和 init|dispose 事件。
- 3)Effect 的生命周期和 View 的耦合,在 ListView 的有些场景下不符合直观的预期。
- 一个 Adapter 和 Component 几乎都是一致的,除了以下几点
- Component 生成一个 Widget,Adapter 生成一个 ListAdapter,ListAdapter 有能力生成一组 Widget。
- 不具体生成 Widget,而是一个 ListAdapter,能非常大的提升页面帧率和流畅度。
- Effect-Lifecycle-Promote
- Component 的 Effect 是跟着 Widget 的生命周期走的,Adapter 的 Effect 是跟着上一级的 Widget 的生命周期走。
- Effect 提升,极大的解除了业务逻辑和视图生命的耦合,即使它的展示还未出现,的其他模块依然能通过 dispatch-api,调用它的能力。
- appear|disappear 的通知
- 由于 Effect 生命周期的提升,我们就能更加精细的区分 init|dispose 和 appear|disappear。而这在 Component 的模型中是无法区分的。
- Reducer is long-lived, Effect is medium-lived, View is short-lived.
- Adapter 的三种实现
- [DynamicFlowAdapter](dynamic-flow-adapter-cn.md)
- [StaticFlowAdapter](static-flow-adapter-cn.md)
- [CustomAdapter](custom-adapter-cn.md)
================================================
FILE: doc/concept/adapter.md
================================================
# Adapter
- In addition to the concept of the underlying Component, we have added a componentized abstract Adapter. Its goal is to solve the 3 problems of the Component model in the ListView scene.
- 1)Putting a "Big-Cell" in the ListView does not enjoy the performance optimization of the ListView code.
- 2)Component cannot distinguish between the appear|disappear and init|dispose events.
- 3)The life cycle of the Effect and the coupling of the View do not meet the intuitive expectations in some scenes of the ListView.
- An Adapter and a Component are almost identical except for the following points
- Component generates a Widget, Adapter generates a ListAdapter, and ListAdapter has the ability to generate a list of Widgets.。
- Not specifically generating a Widget but a ListAdapter can greatly improve the page frame rate and fluency.
- Effect-Lifecycle-Promote
- The Effect of Component follows the life cycle of the Widget, and the Adapter's Effect follows the life cycle of the parent Widget.
- The improvement of the life cycle of the effect greatly removes the coupling between the business logic and the view life. Even if its display has not yet appeared, other modules can still call its capabilities through dispatch-api.
- Appearance|disappear event notification
- As the Effect lifecycle improves, we can more closely distinguish between init|dispose and appear|disappear. This is indistinguishable from the Model's model.
- Reducer is long-lived, Effect is medium-lived, View is short-lived.
- Three implementations of Adapter
- [DynamicFlowAdapter](dynamic-flow-adapter.md)
- [StaticFlowAdapter](static-flow-adapter.md)
- [CustomAdapter](custom-adapter.md)
================================================
FILE: doc/concept/auto-dispose-cn.md
================================================
# Auto-Dispose
- 它是一个非常简易管理生命周期对象的方式。一个 auto-dispose 对象可以自我主动释放,或者在它 follow 的 托管对象释放的时候,释放。
- 在 Effect 中使用的 Context,以及 HigherEffect 中的 EffectPart,都是 auto-dispose 对象。所以我们可以方便的将自定义的需要做生命周期管理的对象托管给它们。
- 示例代码
```dart
class ItemWidgetBindingObserver extends WidgetsBindingObserver
with AutoDispose {
ItemWidgetBindingObserver() : super() {
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (AppConfig.flutterBinding.framesEnabled &&
state == AppLifecycleState.resumed) {
AppConfig.flutterBinding.performReassemble();
}
}
@override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(this);
}
}
void _init(Action action, Context ctx) {
final ItemWidgetBindingObserver observer = ItemWidgetBindingObserver();
observer.follow(ctx);
}
```
================================================
FILE: doc/concept/auto-dispose.md
================================================
# Auto-Dispose
- AutoDispose is a very simple way to manage lifecycle objects. An auto-dispose object can be released on its own initiative or released when the managed object it follows is released.
- The Context used in Effect and the EffectPart in HigherEffect are auto-dispose objects. So we can easily host custom objects that need to be managed for lifecycle management.
- Sample Code
```dart
class ItemWidgetBindingObserver extends WidgetsBindingObserver
with AutoDispose {
ItemWidgetBindingObserver() : super() {
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (AppConfig.flutterBinding.framesEnabled &&
state == AppLifecycleState.resumed) {
AppConfig.flutterBinding.performReassemble();
}
}
@override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(this);
}
}
void _init(Action action, Context ctx) {
final ItemWidgetBindingObserver observer = ItemWidgetBindingObserver();
observer.follow(ctx);
}
```
================================================
FILE: doc/concept/component-cn.md
================================================
# Component
组件是对视图展现和逻辑功能的封装。
面向当下,从 Redux 的视角看,我们对组件分为状态修改的功能(Reducer)和其他。
面向未来,从 UI-Automation 的视角看,我们对组件分为展现表达和其他。
结合上面两个视角,于是我们得到了,View、 Effect、Reducer 三部分,称之为组件的三要素,分别负责了组件的展示、非修改数据的行为、修改数据的操作。
我们以显式配置的方式来完成大组件所依赖的小组件、适配器的注册,这份依赖配置称之为 Dependencies。
所以有了这个公式
Component = View + Effect(可选) + Reducer(可选) + Dependencies(可选)
分治:从组件的角度
集中:从 Store 的角度
================================================
FILE: doc/concept/component.md
================================================
# Component
Component is the encapsulation of view presentation and logic functions.
For the moment, from the perspective of Redux, we divide the component into state-manage functions (Reducers) and others.
Looking to the future, from the perspective of UI-Automation, we divide the component into presentations and others.
Combining the above two perspectives, we got the three parts of View, SideEffect, and Reducer, which are called the three factors of the component.
We use explicit configuration to complete the registration of components and adapters on which large component depend. This dependency configuration is called Dependencies.
So with this formula:
Component = View + Effect(Optional) + Reducer(Optional) + Dependencies(Optional)
Division: From the perspective of the component
Concentration: From the perspective of the Store
================================================
FILE: doc/concept/connector-cn.md
================================================
# Connector
- 它表达了如何从一个大数据中读取小数据,同时对小数据的修改如何同步给大数据,这样的数据连接关系。
- 它是将一个集中式的 Reducer,可以由多层次多模块的小 Reducer 自动拼装的关键。
- 它大大降低了我们使用 Redux 的复杂度。我们不再关心组装过程,我们关心的核心是什么动作促使数据怎么变化。
- 它使用在配置 Dependencies 中,在配置中我们就固化了大组件和小组件之间的连接关系(数据管道),所以在我们使用小组件的时候是不需要传入任何动态参数的。
- 
- Sample Code
```dart
class DetialState {
Profile profile;
String message;
}
ConnOp messageConnector() {
return ConnOp(
get: (DetialState state) => state.message,
set: (DetialState state, String message) => state.message = message,
);
}
```
================================================
FILE: doc/concept/connector.md
================================================
# Connector
- It expresses a data connection relationship of how to read small data from a big data, and how to synchronize to big data when the small data is modified。
- It is the key to a centralized Reducer that can be assembled automatically by a multi-level, multi-module, small Reducer
- It greatly reduces the difficulty of using Redux. We no longer care about the assembly process, we care about what specific actions cause the state to change.
- It is used in the configuration Dependencies, in the configuration we have solidified the connection between the large component and the small component, so we do not need to pass in any dynamic parameters when we use the small component.
- 
- Sample Code
```dart
class DetialState {
Profile profile;
String message;
}
ConnOp messageConnector() {
return ConnOp(
get: (DetialState state) => state.message,
set: (DetialState state, String message) => state.message = message,
);
}
```
================================================
FILE: doc/concept/custom-adapter-cn.md
================================================
# CustomAdapter
- 对大 Cell 的自定义实现
- 要素和 Component 类似,不一样的地方是 Adapter 的视图部分返回的是一个 ListAdapter
- 示例代码
```dart
class CommentAdapter extends Adapter {
CommentAdapter()
: super(
adapter: buildCommentAdapter,
effect: buildCommentEffect(),
reducer: buildCommentReducer(),
);
}
ListAdapter buildCommentAdapter(CommentState state, Dispatch dispatch, ViewService service) {
final List builders = Collections.compact([]
..add((BuildContext buildContext, int index) =>
_buildDetailCommentHeader(state, dispatch, service))
..addAll(_buildCommentViewList(state, dispatch, service))
..add(isEmpty(state.commentListRes?.items)
? (BuildContext buildContext, int index) =>
_buildDetailCommentEmpty(state.itemInfo, dispatch)
: null)
..add(state.commentListRes?.getHasMore() == true
? (BuildContext buildContext, int index) => _buildLoadMore(dispatch)
: null));
return ListAdapter(
(BuildContext buildContext, int index) =>
builders[index](buildContext, index),
builders.length,
);
}
///builds
```
================================================
FILE: doc/concept/custom-adapter.md
================================================
# CustomAdapter
- Custom implementation of large Cell in LisView.
- The Factors of the Adapter are similar to the Component's. The difference is that the view part of the Adapter returns a ListAdapter.
- Sample Code
```dart
class CommentAdapter extends Adapter {
CommentAdapter()
: super(
adapter: buildCommentAdapter,
effect: buildCommentEffect(),
reducer: buildCommentReducer(),
);
}
ListAdapter buildCommentAdapter(CommentState state, Dispatch dispatch, ViewService service) {
final List builders = Collections.compact([]
..add((BuildContext buildContext, int index) =>
_buildDetailCommentHeader(state, dispatch, service))
..addAll(_buildCommentViewList(state, dispatch, service))
..add(isEmpty(state.commentListRes?.items)
? (BuildContext buildContext, int index) =>
_buildDetailCommentEmpty(state.itemInfo, dispatch)
: null)
..add(state.commentListRes?.getHasMore() == true
? (BuildContext buildContext, int index) => _buildLoadMore(dispatch)
: null));
return ListAdapter(
(BuildContext buildContext, int index) =>
builders[index](buildContext, index),
builders.length,
);
}
///builds
```
================================================
FILE: doc/concept/dependencies-cn.md
================================================
# Dependencies
- Dependencies 是一个表达组件之间依赖关系的结构。它接收两个字段
- slots
- {}
- [adapter](adapter-cn.md)
- 它主要包含三方面的信息
- slots,组件依赖的插槽。
- adapter,组件依赖的具体适配器(用来构建高性能的 ListView)。
- [Dependent](dependent-cn.md) 是 subComponent | subAdapter + [connector](connector-cn.md) 的组合。
- 一个 组件的 [Reducer](reducer-cn.md) 由 Component 自身配置的 Reducer 和它的 Dependencies 下的所有子 Reducers 自动复合而成。
- 示例代码
```dart
///register in component
class ItemComponent extends ItemComponent {
ItemComponent()
: super(
view: buildItemView,
reducer: buildItemReducer(),
dependencies: Dependencies(
slots: >{
'appBar': AppBarComponent().asDependent(AppBarConnector()),
'body': ItemBodyComponent().asDependent(ItemBodyConnector()),
'ad_ball': ADBallComponent().asDependent(ADBallConnector()),
'bottomBar': BottomBarComponent().asDependent(BottomBarConnector()),
},
),
);
}
///call in view
Widget buildItemView(ItemState state, Dispatch dispatch, ViewService service) {
return Scaffold(
body: Stack(
children: [
service.buildComponent('body'),
service.buildComponent('ad_ball'),
Positioned(
child: service.buildComponent('bottomBar'),
left: 0.0,
bottom: 0.0,
right: 0.0,
height: 100.0,
),
],
),
appBar: AppbarPreferSize(child: service.buildComponent('appBar')));
}
```
================================================
FILE: doc/concept/dependencies.md
================================================
# Dependencies
- Dependencies is a structure that expresses dependencies between components. It accepts two fields
- slots
- {}
- [adapter](adapter.md)
- It mainly contains three aspects of information
- The slots that the component depends on.
- The adapter that the component depends on (used to build a high-performance ListView).
- [Dependent](dependent.md) Is a combination of subComponent | subAdapter + [connector](connector.md)。
- A component's [Reducer](reducer.md) is automatically compounded by the Reducer configured by the Component itself and all of the Reducers under its Dependencies.
- Sample Code
```dart
///register in component
class ItemComponent extends ItemComponent {
ItemComponent()
: super(
view: buildItemView,
reducer: buildItemReducer(),
dependencies: Dependencies(
slots: >{
'appBar': AppBarComponent().asDependent(AppBarConnector()),
'body': ItemBodyComponent().asDependent(ItemBodyConnector()),
'ad_ball': ADBallComponent().asDependent(ADBallConnector()),
'bottomBar': BottomBarComponent().asDependent(BottomBarConnector()),
},
),
);
}
///call in view
Widget buildItemView(ItemState state, Dispatch dispatch, ViewService service) {
return Scaffold(
body: Stack(
children: [
service.buildComponent('body'),
service.buildComponent('ad_ball'),
Positioned(
child: service.buildComponent('bottomBar'),
left: 0.0,
bottom: 0.0,
right: 0.0,
height: 100.0,
),
],
),
appBar: AppbarPreferSize(child: service.buildComponent('appBar')));
}
```
================================================
FILE: doc/concept/dependent-cn.md
================================================
### Dependent
- Dependent = connector + subComponent | subAdapter 的组合,它表达了小组件|小适配器是如何连接到 Component 的。
- 示例代码
```dart
/// todo
```
================================================
FILE: doc/concept/dependent.md
================================================
### Dependent
- Dependent = connector + subComponent | subAdapter
- It expresses how the small component or adapter are connected to it's parent component.
- Sample Code
```dart
/// todo
```
================================================
FILE: doc/concept/directory-cn.md
================================================
# Directory
推荐的目录结构会是这样
```
sample_page
-- action.dart /// define action types and action creator
-- page.dart /// config a page or component
-- view.dart /// define a function which expresses the presentation of user interface
-- effect.dart /// define a function which handles the side-effect
-- reducer.dart /// define a function which handles state-change
-- state.dart /// define a state and some connector of substate
components
sample_component
-- action.dart
-- component.dart
-- view.dart
-- effect.dart
-- reducer.dart
-- state.dart
```
上层负责组装,下层负责实现。
================================================
FILE: doc/concept/directory.md
================================================
# Directory
The recommended directory structure
```
sample_page
-- action.dart /// define action types and action creator
-- page.dart /// config a page or component
-- view.dart /// define a function which expresses the presentation of user interface
-- effect.dart /// define a function which handles the side-effect
-- reducer.dart /// define a function which handles state-change
-- state.dart /// define a state and some connector of substate
components
sample_component
-- action.dart
-- component.dart
-- view.dart
-- effect.dart
-- reducer.dart
-- state.dart
```
The upper layer is responsible for assembly and the lower layer is responsible for implementation.
================================================
FILE: doc/concept/dynamic-flow-adapter-cn.md
================================================
# DynamicFlowAdapter
- 模版是一个 Map,接受一个数组类型的数据驱动
- 示例代码
```dart
class RecommendAdapter extends DynamicFlowAdapter {
RecommendAdapter()
: super(
pool: >{
'card_0': RecommendTitleComponent(),
'card_1': RecommendRowComponent(),
},
connector: RecommendCardListConnector(),
);
}
```
================================================
FILE: doc/concept/dynamic-flow-adapter.md
================================================
# DynamicFlowAdapter
- The template is a Map that accepts an array-like data driven
- Sample Code
```dart
class RecommendAdapter extends DynamicFlowAdapter {
RecommendAdapter()
: super(
pool: >{
'card_0': RecommendTitleComponent(),
'card_1': RecommendRowComponent(),
},
connector: RecommendCardListConnector(),
);
}
```
================================================
FILE: doc/concept/effect-cn.md
================================================
# Effect
Effect顾名思义,用于处理Action的副作用。
我估摸着有人就要问我了,副作用是啥玩意?
打个比方吧,假如我拥有一个函数 `f()`
```text
fn f(x):
return x * 1
```
此时此刻,另一个函数 `g()`
```text
fn g(x):
changeSystemEntropy()
return ax ^ 2 + bx + c
```
我们可以发现,`g()`里边有个改变系统熵的行为。这在函数式编程思想中,就叫做副作用,因为它可能影响到除了这个函数内部自身状态以外的其他状态。
在Fish-Redux中同样,我们通过 `dispatch()` 一些action实现状态修改,但是相对于状态来说,对外部的操作,类似于 `SystemChrome.setSystemUIOverlayStyle()`这样的操作,都是副作用。
现在介绍完了副作用,也没啥可介绍的了。
Effect用法跟Reducer差不太多,但是作用完全不同。
除了上面介绍的场景之外,异步请求也是一个经常会有的情况,这时候Effect可以帮你方便的解决这些问题。
你可以通过控制effect的返回值来达到某些目的,默认情况下,effect会在reducer之前被执行。
当前effect返回 `true` 的时候,就会停止后续的effect和reducer的操作
当前effect返回 `false` 的时候,后续effect和reducer继续执行
- Effect 是一个处理所有副作用的函数。它接收下面的参数
- Action action
- Context context
- BuildContext context
- T state
- dispatch
- isDisposed
Effect会接收来自 View 的“意图”,包括对应的生命周期的回调,然后做出具体的执行。
- 它的处理可能是一个异步函数,数据可能在过程中被修改,所以我们应该通过 context.state 获取最新数据。
- 如果它要修改数据,应该发一个 Action 到 Reducer 里去处理。它对数据是只读的,不能直接去修改数据。
- 如果它的返回值是一个非空值,则代表自己优先处理,不再做下一步的动作;否则广播给其他组件的 Effect 部分,同时发送给 Reducer。
> Self-First-Broadcast。
> 
- 示例代码
```dart
/// one style of writing
FutureOr