Skip to content

Commit

Permalink
Remove connector.set & clone in redux
Browse files Browse the repository at this point in the history
  • Loading branch information
zjuwjf committed Mar 25, 2019
1 parent 50ce9a9 commit 4fe38d7
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 79 deletions.
2 changes: 1 addition & 1 deletion example/lib/todo_list_page/list_adapter/adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ToDoListAdapter extends DynamicFlowAdapter<PageState> {
);
}

class _ToDoListConnector implements Connector<PageState, List<ItemBean>> {
class _ToDoListConnector extends Connector<PageState, List<ItemBean>> {
@override
List<ItemBean> get(PageState state) {
if (state.toDos?.isNotEmpty == true) {
Expand Down
24 changes: 3 additions & 21 deletions lib/src/redux/basic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'dart:async';
/// Store<T> ---- State management center
/// 2. Additional abstractions beyond the basic concepts of the ReduxJs community.
/// Connector<S, P> ---- The connection between big object <T> and small object <P>
/// Cloneable ---- Clone an object
/// SubReducer<T> ---- A function that modifies data of partial <T>
/// The role of this layer of abstraction
/// a. It is obvious that the implementation of combineReducers are decoupled with the grammatical features of JS
Expand Down Expand Up @@ -83,29 +82,12 @@ typedef StoreEnhancer<T> = StoreCreator<T> Function(StoreCreator<T> creator);
/// Ensure that a T will be cloned at most once during the entire process.
typedef SubReducer<T> = T Function(T state, Action action, bool isStateCopied);

/// Definition of Cloneable
abstract class Cloneable<T extends Cloneable<T>> {
T clone();
}

/// Definition of Connector
/// 1. How to get an object of type P from an object of type S.
/// 2. How to synchronize change of an object of type P to an object of type S.
abstract class Connector<S, P> {
factory Connector({P Function(S) get, void Function(S, P) set}) =>
_Connector<S, P>(get, set);

abstract class AbstractConnector<S, P> {
P get(S state);
void set(S state, P subState);
}

/// An implementation of the default Connector<S, P>
class _Connector<S, P> implements Connector<S, P> {
final P Function(S) getter;
final void Function(S, P) setter;
const _Connector(this.getter, this.setter);
@override
P get(S state) => getter(state);
@override
void set(S state, P subState) => setter(state, subState);
/// Todo
SubReducer<S> subReducer(Reducer<P> reducer);
}
33 changes: 0 additions & 33 deletions lib/src/redux/combine_reducers.dart
Original file line number Diff line number Diff line change
@@ -1,38 +1,5 @@
import 'basic.dart';

/// how to clone an object
dynamic _clone<T>(T state) {
if (state is Cloneable) {
return state.clone();
} else if (state is List) {
return state.toList();
} else if (state is Map<String, dynamic>) {
return <String, dynamic>{}..addAll(state);
} else if (state == null) {
return null;
} else {
throw ArgumentError(
'Could not clone this state of type ${state.runtimeType}.');
}
}

/// Connector<T, P> + Reducer<P> => SubReducer<T>
SubReducer<T> subReducer<T, P>(Connector<T, P> connector, Reducer<P> reducer) {
return (T state, Action action, bool isStateCopied) {
final P props = connector.get(state);
if (props == null) {
return state;
}
final P newProps = reducer(props, action);
final bool hasChanged = newProps != props;
final T copy = (hasChanged && !isStateCopied) ? _clone<T>(state) : state;
if (hasChanged) {
connector.set(copy, newProps);
}
return copy;
};
}

/// Combine an iterable of SubReducer<T> into one Reducer<T>
Reducer<T> combineSubReducers<T>(Iterable<SubReducer<T>> subReducers) {
final List<SubReducer<T>> notNullReducers = subReducers
Expand Down
6 changes: 3 additions & 3 deletions lib/src/redux_adapter/dynamic_flow_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DynamicFlowAdapter<T> extends Logic<T>
with RecycleContextMixin<T>
implements AbstractAdapter<T> {
final Map<String, AbstractLogic<Object>> pool;
final Connector<T, List<ItemBean>> connector;
final AbstractConnector<T, List<ItemBean>> connector;

DynamicFlowAdapter({
@required this.pool,
Expand Down Expand Up @@ -112,7 +112,7 @@ class DynamicFlowAdapter<T> extends Logic<T>
Reducer<T> _dynamicReducer<T>(
Reducer<T> reducer,
Map<String, AbstractLogic<Object>> pool,
Connector<T, List<ItemBean>> connector,
AbstractConnector<T, List<ItemBean>> connector,
) {
final Reducer<List<ItemBean>> dyReducer =
(List<ItemBean> state, Action action) {
Expand All @@ -133,7 +133,7 @@ Reducer<T> _dynamicReducer<T>(

return combineReducers(<Reducer<T>>[
reducer,
combineSubReducers(<SubReducer<T>>[subReducer(connector, dyReducer)]),
combineSubReducers(<SubReducer<T>>[connector.subReducer(dyReducer)]),
]);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/redux_component/basic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ abstract class AbstractLogic<T> {
Object key(T state);

/// It's a convenient way to create a dependency
Dependent<K> asDependent<K>(Connector<K, T> connector);
Dependent<K> asDependent<K>(AbstractConnector<K, T> connector);

/// Find a dependent by name
Dependent<T> slot(String name);
Expand Down
66 changes: 64 additions & 2 deletions lib/src/redux_component/connector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,68 @@ import 'basic.dart';
import 'dependent.dart';
import 'logic.dart';

class ConnOp<S, P> implements Connector<S, P> {
/// Definition of Cloneable
abstract class Cloneable<T extends Cloneable<T>> {
T clone();
}

/// how to clone an object
dynamic _clone<T>(T state) {
if (state is Cloneable) {
return state.clone();
} else if (state is List) {
return state.toList();
} else if (state is Map<String, dynamic>) {
return <String, dynamic>{}..addAll(state);
} else if (state == null) {
return null;
} else {
throw ArgumentError(
'Could not clone this state of type ${state.runtimeType}.');
}
}

abstract class BaseConn<T, P> implements AbstractConnector<T, P> {
const BaseConn();

void set(T state, P subState);

@override
SubReducer<T> subReducer(Reducer<P> reducer) {
return (T state, Action action, bool isStateCopied) {
final P props = get(state);
if (props == null) {
return state;
}
final P newProps = reducer(props, action);
final bool hasChanged = newProps != props;
final T copy = (hasChanged && !isStateCopied) ? _clone<T>(state) : state;
if (hasChanged) {
set(copy, newProps);
}
return copy;
};
}
}

class Connector<T, P> extends BaseConn<T, P> {
final P Function(T) _getter;
final void Function(T, P) _setter;

const Connector({
P Function(T) get,
void Function(T, P) set,
}) : _getter = get,
_setter = set;

@override
P get(T state) => _getter(state);

@override
void set(T state, P subState) => _setter(state, subState);
}

class ConnOp<S, P> extends BaseConn<S, P> {
final P Function(S) _getter;
final void Function(S, P) _setter;

Expand Down Expand Up @@ -34,7 +95,8 @@ abstract class MapLike {
_fieldsMap = <String, Object>{}..addAll(from._fieldsMap);
}

Connector<T, P> withMapLike<T extends MapLike, P>(String key) => ConnOp<T, P>(
AbstractConnector<T, P> withMapLike<T extends MapLike, P>(String key) =>
ConnOp<T, P>(
get: (T state) => state[key],
set: (T state, P sub) => state[key] = sub,
);
Expand Down
6 changes: 3 additions & 3 deletions lib/src/redux_component/dependent.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '../redux/redux.dart';
import 'basic.dart';

class _Dependent<T, P> implements Dependent<T> {
final Connector<T, P> connector;
final AbstractConnector<T, P> connector;
final AbstractLogic<P> factors;

_Dependent({
Expand All @@ -17,7 +17,7 @@ class _Dependent<T, P> implements Dependent<T> {
@override
SubReducer<T> createSubReducer() {
final Reducer<P> reducer = factors.reducer;
return reducer != null ? subReducer(connector, reducer) : null;
return reducer != null ? connector.subReducer(reducer) : null;
}

@override
Expand Down Expand Up @@ -59,5 +59,5 @@ class _Dependent<T, P> implements Dependent<T> {
}

Dependent<K> createDependent<K, T>(
Connector<K, T> connector, Logic<T> factors) =>
AbstractConnector<K, T> connector, Logic<T> factors) =>
_Dependent<K, T>(connector: connector, factors: factors);
2 changes: 1 addition & 1 deletion lib/src/redux_component/logic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class Logic<T> implements AbstractLogic<T> {
Dependent<T> slot(String type) => dependencies?.slot(type);

@override
Dependent<K> asDependent<K>(Connector<K, T> connector) =>
Dependent<K> asDependent<K>(AbstractConnector<K, T> connector) =>
createDependent<K, T>(connector, this);

@override
Expand Down
2 changes: 1 addition & 1 deletion test/page_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ void main() {
track.append('onReduce', state.clone());
}),
higherEffect: toDoListHigherEffect,
middlewares: <Middleware<ToDoList>>[
middleware: <Middleware<ToDoList>>[
instrumentMiddleware<ToDoList>(toDoListMiddleware,
pre: (action, getState) {
if (action.type == ToDoListAction.middlewareEdit) {
Expand Down
4 changes: 2 additions & 2 deletions test/test_widgets/lib/page/page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ Composable<Dispatch> toDoListMiddleware({
Dispatch dispatch,
Get<ToDoList> getState,
}) =>
(next) => (Action action) {
(Dispatch next) => (Action action) {
if (action.type == ToDoListAction.middlewareEdit) {
assert(action.payload is Todo);

Expand Down Expand Up @@ -286,5 +286,5 @@ Widget createPageWidget(BuildContext context) {
effect: toDoListEffectAsync,
// shouldUpdate: forbidRefreshWhenAddOrRemove,
// onError: toDoListErrorHandler,
middlewares: [toDoListMiddleware]).buildPage(pageInitParams);
middleware: [toDoListMiddleware]).buildPage(pageInitParams);
}
4 changes: 2 additions & 2 deletions test/test_widgets/lib/test_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class _StubState extends State<TestStub> {
class TestPage<T extends Cloneable<T>, P> extends Page<T, P> {
TestPage({
@required InitState<T, P> initState,
List<Middleware<T>> middlewares,
List<Middleware<T>> middleware,
@required ViewBuilder<T> view,
Reducer<T> reducer,
ReducerFilter<T> filter,
Expand All @@ -38,7 +38,7 @@ class TestPage<T extends Cloneable<T>, P> extends Page<T, P> {
Key Function(T) key,
}) : super(
initState: initState,
middleware: middlewares,
middleware: middleware,
view: view,
reducer: reducer,
filter: filter,
Expand Down
18 changes: 9 additions & 9 deletions test/test_widgets/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ name: test_widgets
description: widgets for redux test...

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
sdk: '>=2.0.0-dev.28.0 <3.0.0'

dependencies:
flutter:
sdk: flutter
fish_redux:
path: ../../
flutter:
sdk: flutter
fish_redux:
path: ../../

dev_dependencies:
flutter_driver:
sdk: flutter
flutter_test:
sdk: flutter
flutter_driver:
sdk: flutter
flutter_test:
sdk: flutter

0 comments on commit 4fe38d7

Please sign in to comment.