Skip to content

Commit

Permalink
Add StateKey #461
Browse files Browse the repository at this point in the history
  • Loading branch information
zjuwjf committed Sep 24, 2019
1 parent 102a22f commit 6ca22fe
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 39 deletions.
3 changes: 2 additions & 1 deletion lib/src/redux_adapter/adapter.dart
Expand Up @@ -15,7 +15,7 @@ abstract class Adapter<T> extends Logic<T> implements AbstractAdapter<T> {
ReducerFilter<T> filter,
Effect<T> effect,
Dependencies<T> dependencies,
Object Function(T) key,
@deprecated Object Function(T) key,
}) : assert(adapter != null),
assert(dependencies?.adapter == null,
'Unexpected dependencies.list for Adapter.'),
Expand All @@ -25,6 +25,7 @@ abstract class Adapter<T> extends Logic<T> implements AbstractAdapter<T> {
filter: filter,
effect: effect,
dependencies: dependencies,
// ignore:deprecated_member_use_from_same_package
key: key,
);

Expand Down
67 changes: 35 additions & 32 deletions lib/src/redux_adapter/dynamic_flow_adapter.dart
Expand Up @@ -6,12 +6,12 @@ import '../utils/utils.dart';
import 'recycle_context.dart';

class ItemBean {
String type;
Object data;
final String type;
final Object data;

ItemBean(this.type, this.data);
const ItemBean(this.type, this.data);

ItemBean clone() => ItemBean(type, data);
ItemBean clone({String type, Object data}) => ItemBean(type, data);
}

/// template is a map, driven by array
Expand All @@ -25,12 +25,19 @@ class DynamicFlowAdapter<T> extends Logic<T> with RecycleContextMixin<T> {
ReducerFilter<T> filter,
Reducer<T> reducer,
Effect<T> effect,
Object Function(T) key,

/// implement [StateKey] in T instead of using key in Logic.
/// class T implements StateKey {
/// Object _key = UniqueKey();
/// Object key() => _key;
/// }
@deprecated Object Function(T) key,
}) : super(
reducer: _dynamicReducer(reducer, pool, connector),
effect: effect,
filter: filter,
dependencies: null,
// ignore:deprecated_member_use_from_same_package
key: key,
);

Expand Down Expand Up @@ -100,7 +107,7 @@ Reducer<T> _dynamicReducer<T>(
final Object newData = result.onReducer(itemBean.data, action);
if (newData != itemBean.data) {
copy ??= state.toList();
copy[i] = itemBean.clone()..data = newData;
copy[i] = itemBean.clone(data: newData);
}
}
}
Expand All @@ -121,39 +128,35 @@ Reducer<T> _dynamicReducer<T>(
/// frame. in this time the sub component will use cache state.
Get<Object> _subGetter(Get<List<ItemBean>> getter, int index) {
final List<ItemBean> curState = getter();
final Object subCache = curState[index].data;
ItemBean cacheItem = curState[index];

return () {
final List<ItemBean> newState = getter();

/// Either all sub-components use cache or not.
if (_isSimilar(curState, newState)) {
return newState[index].data;
} else {
return subCache;
if (newState != null && newState.length > index) {
final ItemBean newItem = newState[index];
if (_couldReuse(cacheItem, newItem)) {
cacheItem = newItem;
}
}

return cacheItem.data;
};
}

/// Judge [oldList] and [newList] is similar
///
/// if true: means the list size and every itemBean type & data.runtimeType
/// is equal.
bool _isSimilar(
List<ItemBean> oldList,
List<ItemBean> newList,
) {
if (oldList != newList &&
oldList?.length == newList.length &&
Collections.isNotEmpty(newList)) {
bool isEvery = true;
for (int i = 0; i < newList.length; i++) {
if (oldList[i].type != newList[i].type ||
oldList[i].data.runtimeType != newList[i].data.runtimeType) {
isEvery = false;
break;
}
}
return isEvery;
bool _couldReuse(ItemBean beanA, ItemBean beanB) {
if (beanA.type != beanB.type) {
return false;
}
return false;

final Object dataA = beanA.data;
final Object dataB = beanB.data;
if (dataA.runtimeType != dataB.runtimeType) {
return false;
}

final Object keyA = dataA is StateKey ? dataA.key() : null;
final Object keyB = dataB is StateKey ? dataB.key() : null;
return keyA == keyB;
}
9 changes: 8 additions & 1 deletion lib/src/redux_adapter/static_flow_adapter.dart
Expand Up @@ -16,7 +16,13 @@ class StaticFlowAdapter<T> extends Logic<T>
Reducer<T> reducer,
Effect<T> effect,
ReducerFilter<T> filter,
Object Function(T) key,

/// implement [StateKey] in T instead of using key in Logic.
/// class T implements StateKey {
/// Object _key = UniqueKey();
/// Object key() => _key;
/// }
@deprecated Object Function(T) key,
}) : assert(slots != null),
_slots = Collections.compact(slots),
super(
Expand All @@ -31,6 +37,7 @@ class StaticFlowAdapter<T> extends Logic<T>
effect: effect,
filter: filter,
dependencies: null,
// ignore:deprecated_member_use_from_same_package
key: key,
);

Expand Down
12 changes: 11 additions & 1 deletion lib/src/redux_component/basic.dart
Expand Up @@ -327,7 +327,17 @@ abstract class AbstractAdapter<T> implements AbstractLogic<T> {
/// When a reducer is slow to handle an action, maybe we should use ReducerFilter to improve the performance.
typedef ReducerFilter<T> = bool Function(T state, Action action);

///
/// implement [StateKey] in T .
/// class T implements StateKey {
/// Object _key = UniqueKey();
/// Object key() => _key;
/// }
/// see [https://github.com/alibaba/fish-redux/issues/461]
abstract class StateKey {
Object key();
}

/// Define a DispatchBus
abstract class DispatchBus {
void attach(DispatchBus parent);

Expand Down
9 changes: 8 additions & 1 deletion lib/src/redux_component/component.dart
Expand Up @@ -32,7 +32,13 @@ abstract class Component<T> extends Logic<T> implements AbstractComponent<T> {
Dependencies<T> dependencies,
ShouldUpdate<T> shouldUpdate,
WidgetWrapper wrapper,
Key Function(T) key,

/// implement [StateKey] in T instead of using key in Logic.
/// class T implements StateKey {
/// Object _key = UniqueKey();
/// Object key() => _key;
/// }
@deprecated Key Function(T) key,
bool clearOnDependenciesChanged = false,
}) : assert(view != null),
_view = view,
Expand All @@ -44,6 +50,7 @@ abstract class Component<T> extends Logic<T> implements AbstractComponent<T> {
filter: filter,
effect: effect,
dependencies: dependencies,
// ignore:deprecated_member_use_from_same_package
key: key,
);

Expand Down
19 changes: 17 additions & 2 deletions lib/src/redux_component/logic.dart
Expand Up @@ -33,12 +33,25 @@ abstract class Logic<T> implements AbstractLogic<T> {
Dependencies<T> dependencies,
ReducerFilter<T> filter,
Effect<T> effect,
Object Function(T state) key,

/// implement [StateKey] in T instead of using key in Logic.
/// class T implements StateKey {
/// Object _key = UniqueKey();
/// Object key() => _key;
/// }
@deprecated Object Function(T state) key,
}) : _reducer = reducer,
_filter = filter,
_effect = effect,
_dependencies = dependencies,
_key = key;
// ignore:deprecated_member_use_from_same_package
assert(isAssignFrom<T, StateKey>() == false || key == null,
'Implements [StateKey] in T instead of using key in Logic.'),
_key = isAssignFrom<T, StateKey>()
// ignore:avoid_as
? ((T state) => (state as StateKey).key())
// ignore:deprecated_member_use_from_same_package
: key;

@override
Type get propertyType => T;
Expand All @@ -47,6 +60,8 @@ abstract class Logic<T> implements AbstractLogic<T> {

bool isTypeof<K>() => Tuple0<T>() is Tuple0<K>;

static bool isAssignFrom<P, Q>() => Tuple0<P>() is Tuple0<Q>;

/// if
/// _resultCache['key'] = null;
/// then
Expand Down
9 changes: 8 additions & 1 deletion lib/src/redux_component/page.dart
Expand Up @@ -34,7 +34,13 @@ abstract class Page<T, P> extends Component<T> {
Dependencies<T> dependencies,
ShouldUpdate<T> shouldUpdate,
WidgetWrapper wrapper,
Key Function(T) key,

/// implement [StateKey] in T instead of using key in Logic.
/// class T implements StateKey {
/// Object _key = UniqueKey();
/// Object key() => _key;
/// }
@deprecated Key Function(T) key,
List<Middleware<T>> middleware,
List<ViewMiddleware<T>> viewMiddleware,
List<EffectMiddleware<T>> effectMiddleware,
Expand All @@ -55,6 +61,7 @@ abstract class Page<T, P> extends Component<T> {
effect: effect,
shouldUpdate: shouldUpdate,
wrapper: wrapper,
// ignore:deprecated_member_use_from_same_package
key: key,
);

Expand Down

0 comments on commit 6ca22fe

Please sign in to comment.