Skip to content

Commit

Permalink
Merge branch 'master' into develop
Browse files Browse the repository at this point in the history
* master:
  Fixed Page class name duplication
  add unit test for collection util and map like connector
  📝 (docs) 增加 利用 docsify 生成的文档, 便于阅读和查看, 需要设置 开启  github pages
  fix: fix spell error on PureViewWidget
  Fix typo

# Conflicts:
#	example/lib/app.dart
#	lib/src/redux_component_mixin/keep_alive_mixin.dart
#	lib/src/redux_component_mixin/single_ticker_provider_mixin.dart
#	lib/src/redux_component_mixin/ticker_provider_mixin.dart
#	lib/src/redux_component_mixin/widgets_binding_observer_mixin.dart
#	lib/src/redux_routes/page_routes.dart
#	test/test_widgets/lib/adapter/adapter.dart
#	test/test_widgets/lib/adapter/page.dart
#	test/test_widgets/lib/test_base.dart
  • Loading branch information
zjuwjf committed Apr 14, 2020
2 parents fe7941e + 8d52fd6 commit 05ea6f4
Show file tree
Hide file tree
Showing 81 changed files with 2,196 additions and 10 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ android/local.properties

# docs
node_modules/
docs/
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## [0.3.2]
- Fixed Page class name duplication

## [0.3.1]
- rename AdapterSource’s api
- add PureViewComponent
Expand Down
Empty file added docs/.nojekyll
Empty file.
79 changes: 79 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<p align="center"><img src="https://img.alicdn.com/tfs/TB1r74NJyLaK1RjSZFxXXamPFXa-1024-1024.png" align="center" width="175"></p>
<h1 align="center">Fish Redux</h1>

[![Build Status](https://travis-ci.org/alibaba/fish-redux.svg?branch=master)](https://travis-ci.org/alibaba/fish-redux) [![pub package](https://img.shields.io/pub/v/fish_redux.svg)](https://pub.dartlang.org/packages/fish_redux) [![codecov](https://codecov.io/gh/alibaba/fish-redux/branch/master/graph/badge.svg)](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

<img src="https://img.alicdn.com/tfs/TB1pkhoJr2pK1RjSZFsXXaNlXXa-1004-1370.png" width="500px" height="680px">

## Installation

[Go](https://pub.dartlang.org/packages/fish_redux#-installing-tab-)

## Documentation

Language: [English](/) | [中文简体](/zh-cn/)

## 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

订阅地址

<img src="https://img.alicdn.com/tfs/TB17Ki5XubviK0jSZFNXXaApXXa-656-656.png" width="328px" height="328px">

[For English](https://twitter.com/xianyutech "For English")
2 changes: 2 additions & 0 deletions docs/_navbar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* [En](/)
* [中文](/zh-cn/)
28 changes: 28 additions & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
* [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)
* [What's the difference between 'Fish Redux' and 'Redux' ?](concept/what's-the-diiference.md)
* [What's-adapter](concept/what's-adapter.md)
* [What's-connector](concept/what's-connector.md)
* [Mechanism](concept/mechanism.md)
* [Directory](concept/directory.md)
2 changes: 2 additions & 0 deletions docs/concept/_navbar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* [En](/)
* [中文](/zh-cn/)
28 changes: 28 additions & 0 deletions docs/concept/_sidebar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
* [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)
* [What's the difference between 'Fish Redux' and 'Redux' ?](concept/what's-the-diiference.md)
* [What's-adapter](concept/what's-adapter.md)
* [What's-connector](concept/what's-connector.md)
* [Mechanism](concept/mechanism.md)
* [Directory](concept/directory.md)
29 changes: 29 additions & 0 deletions docs/concept/action.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 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<String, Object> payload) {
return Action(MessageAction.onShare, payload: payload);
}
static Action shared() {
return const Action(MessageAction.shared);
}
}
```
23 changes: 23 additions & 0 deletions docs/concept/adapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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)
34 changes: 34 additions & 0 deletions docs/concept/auto-dispose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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<ItemPageContainerState> ctx) {
final ItemWidgetBindingObserver observer = ItemWidgetBindingObserver();
observer.follow(ctx);
}
```
18 changes: 18 additions & 0 deletions docs/concept/component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 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
<img src="https://img.alicdn.com/tfs/TB1vqB2J4YaK1RjSZFnXXa80pXa-900-780.png" width="450px" height="390px">

Concentration: From the perspective of the Store
<img src="https://img.alicdn.com/tfs/TB1sThMJYvpK1RjSZFqXXcXUVXa-1426-762.png" width="713px" height="381px">
23 changes: 23 additions & 0 deletions docs/concept/connector.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Connector<T, P>

- 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.
- ![image.png | left | 719x375](https://cdn.nlark.com/lark/0/2018/png/82574/1545365202743-01074be7-f067-45c7-aae0-91b12cd50ae6.png)

- Sample Code

```dart
class DetialState {
Profile profile;
String message;
}
ConnOp<DetialState, String> messageConnector() {
return ConnOp<DetialState, String>(
get: (DetialState state) => state.message,
set: (DetialState state, String message) => state.message = message,
);
}
```
37 changes: 37 additions & 0 deletions docs/concept/custom-adapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 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<CommentState> {
CommentAdapter()
: super(
adapter: buildCommentAdapter,
effect: buildCommentEffect(),
reducer: buildCommentReducer(),
);
}
ListAdapter buildCommentAdapter(CommentState state, Dispatch dispatch, ViewService service) {
final List<IndexedWidgetBuilder> builders = Collections.compact(<IndexedWidgetBuilder>[]
..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
```
50 changes: 50 additions & 0 deletions docs/concept/dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Dependencies

- Dependencies is a structure that expresses dependencies between components. It accepts two fields
- slots
- <String, [Dependent](dependent.md)>{}
- [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<ItemState> {
ItemComponent()
: super(
view: buildItemView,
reducer: buildItemReducer(),
dependencies: Dependencies<ItemState>(
slots: <String, Dependent<ItemState>>{
'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: <Widget>[
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')));
}
```
9 changes: 9 additions & 0 deletions docs/concept/dependent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### Dependent

- Dependent = connector<T, P> + subComponent | subAdapter
- It expresses how the small component or adapter are connected to it's parent component.
- Sample Code

```dart
/// todo
```
Loading

0 comments on commit 05ea6f4

Please sign in to comment.