Skip to content

Commit

Permalink
Add SourceFlowAdapter
Browse files Browse the repository at this point in the history
  • Loading branch information
zjuwjf committed Nov 8, 2019
1 parent a66bb6b commit a134cde
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 130 deletions.
176 changes: 46 additions & 130 deletions lib/src/redux_adapter/dynamic_flow_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import '../redux_component/redux_component.dart';
import '../utils/utils.dart';
import 'recycle_context.dart';

/// Use [AdapterSource] instead of [List<ItemBean>]
// @deprecated
class ItemBean {
final String type;
final Object data;
Expand All @@ -17,93 +15,14 @@ class ItemBean {
ItemBean(type ?? this.type, data ?? this.data);
}

abstract class AdapterSource {
int get itemCount;

String getType(int index);

Object getData(int index);

AdapterSource update(int index, Object data, bool isStateCopied);
}

abstract class MutableSource extends AdapterSource {
@mustCallSuper
@override
MutableSource update(int index, Object data, bool isStateCopied) {
final MutableSource result = isStateCopied ? this : clone();
return result..setData(index, data);
}

void setData(int index, Object data);

MutableSource clone();
}

abstract class ImmutableSource extends AdapterSource {
@mustCallSuper
@override
ImmutableSource update(int index, Object data, bool isStateCopied) =>
setData(index, data);

ImmutableSource setData(int index, Object data);

ImmutableSource clone();
}

class _Conn<T> implements AbstractConnector<T, AdapterSource> {
final AbstractConnector<T, List<ItemBean>> connector;

_Conn(this.connector);

@override
AdapterSource get(T state) => _ListSource(connector.get(state));

@override
SubReducer<T> subReducer(Reducer<AdapterSource> reducer) {
return connector.subReducer((List<ItemBean> list, Action action) {
/// maybe a long loop
final _ListSource listSource = reducer(_ListSource(list), action);
return listSource.list;
});
}
}

class _ListSource extends MutableSource {
/// ignore:deprecated_member_use_from_same_package
final List<ItemBean> list;

_ListSource(this.list);

@override
MutableSource clone() => _ListSource(list.toList());

@override
Object getData(int index) => list[index].data;

@override
String getType(int index) => list[index].type;

@override
int get itemCount => list.length;

@override
void setData(int index, Object data) =>
list[index] = ItemBean(list[index].type, data);
}

/// template is a map, driven by array
class DynamicFlowAdapter<T> extends Logic<T> with RecycleContextMixin<T> {
final Map<String, AbstractLogic<Object>> pool;

final AbstractConnector<T, AdapterSource> sourceConn;
final AbstractConnector<T, List<ItemBean>> connector;

DynamicFlowAdapter({
@required this.pool,

/// ignore:deprecated_member_use_from_same_package
@deprecated AbstractConnector<T, List<ItemBean>> connector,
@required AbstractConnector<T, AdapterSource> sourceConn2,
@required this.connector,
ReducerFilter<T> filter,
Reducer<T> reducer,
Effect<T> effect,
Expand All @@ -114,10 +33,8 @@ class DynamicFlowAdapter<T> extends Logic<T> with RecycleContextMixin<T> {
/// Object key() => _key;
/// }
@deprecated Object Function(T) key,
}) : sourceConn = sourceConn2 ?? _Conn<T>(connector),
super(
reducer: _dynamicReducer(
reducer, pool, sourceConn2 ?? _Conn<T>(connector)),
}) : super(
reducer: _dynamicReducer(reducer, pool, connector),
effect: effect,
filter: filter,
dependencies: null,
Expand All @@ -127,31 +44,31 @@ class DynamicFlowAdapter<T> extends Logic<T> with RecycleContextMixin<T> {

@override
ListAdapter buildAdapter(ContextSys<T> ctx) {
final AdapterSource adapterSource = sourceConn.get(ctx.state);
assert(adapterSource != null);
final List<ItemBean> list = connector.get(ctx.state);
assert(list != null);

final RecycleContext<T> recycleCtx = ctx;
final List<ListAdapter> adapters = <ListAdapter>[];

recycleCtx.markAllUnused();

for (int index = 0; index < adapterSource.itemCount; index++) {
final String type = adapterSource.getType(index);
for (int index = 0; index < list.length; index++) {
final ItemBean itemBean = list[index];
final String type = itemBean.type;
final AbstractLogic<Object> result = pool[type];

assert(
result != null, 'Type of $type has not benn registered in the pool.');
if (result != null) {
if (result is AbstractAdapter<Object>) {
final ContextSys<Object> subCtx = recycleCtx.reuseOrCreate(
Tuple2<Type, Object>(
result.runtimeType,
result.key(adapterSource.getData(index)),
result.key(itemBean.data),
),
() => result.createContext(
recycleCtx.store,
recycleCtx.context,
_subGetter(() => sourceConn.get(recycleCtx.state), index),
_subGetter(() => connector.get(recycleCtx.state), index),
bus: recycleCtx.bus,
enhancer: recycleCtx.enhancer,
),
Expand All @@ -161,7 +78,7 @@ class DynamicFlowAdapter<T> extends Logic<T> with RecycleContextMixin<T> {
adapters.add(ListAdapter((BuildContext buildContext, int _) {
return result.buildComponent(
recycleCtx.store,
_subGetter(() => sourceConn.get(recycleCtx.state), index),
_subGetter(() => connector.get(recycleCtx.state), index),
bus: recycleCtx.bus,
enhancer: recycleCtx.enhancer,
);
Expand All @@ -179,18 +96,19 @@ class DynamicFlowAdapter<T> extends Logic<T> with RecycleContextMixin<T> {
Reducer<T> _dynamicReducer<T>(
Reducer<T> reducer,
Map<String, AbstractLogic<Object>> pool,
AbstractConnector<T, AdapterSource> connector,
AbstractConnector<T, List<ItemBean>> connector,
) {
final Reducer<AdapterSource> dyReducer =
(AdapterSource state, Action action) {
AdapterSource copy;
for (int i = 0; i < state.itemCount; i++) {
final AbstractLogic<Object> result = pool[state.getType(i)];
final Reducer<List<ItemBean>> dyReducer =
(List<ItemBean> state, Action action) {
List<ItemBean> copy;
for (int i = 0; i < state.length; i++) {
final ItemBean itemBean = state[i];
final AbstractLogic<Object> result = pool[itemBean.type];
if (result != null) {
final Object oldData = state.getData(i);
final Object newData = result.onReducer(oldData, action);
if (newData != oldData) {
copy = state.update(i, newData, copy != null);
final Object newData = result.onReducer(itemBean.data, action);
if (newData != itemBean.data) {
copy ??= state.toList();
copy[i] = itemBean.clone(data: newData);
}
}
}
Expand All @@ -209,39 +127,37 @@ Reducer<T> _dynamicReducer<T>(
/// [_isSimilar] return false we should use cache state before reducer invoke.
/// for reducer change state immediately but sub component will refresh on next
/// frame. in this time the sub component will use cache state.
Get<Object> _subGetter(Get<AdapterSource> getter, int index) {
final AdapterSource curState = getter();
String type = curState.getType(index);
Object data = curState.getData(index);
Get<Object> _subGetter(Get<List<ItemBean>> getter, int index) {
final List<ItemBean> curState = getter();
ItemBean cacheItem = curState[index];

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

/// Either all sub-components use cache or not.
if (newState != null && newState.itemCount > index) {
final String newType = newState.getType(index);
final Object newData = newState.getData(index);

if (_couldReuse(
typeA: type,
typeB: newType,
dataA: data,
dataB: newData,
)) {
type = newType;
data = newData;
if (newState != null && newState.length > index) {
final ItemBean newItem = newState[index];
if (_couldReuse(cacheItem, newItem)) {
cacheItem = newItem;
}
}

return data;
return cacheItem.data;
};
}

bool _couldReuse({String typeA, String typeB, Object dataA, Object dataB}) {
return typeA != typeB
? false
: dataA.runtimeType != dataB.runtimeType
? false
: (dataA is StateKey ? dataA.key() : null) ==
(dataB is StateKey ? dataB.key() : null);
bool _couldReuse(ItemBean beanA, ItemBean beanB) {
if (beanA.type != beanB.type) {
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;
}
1 change: 1 addition & 0 deletions lib/src/redux_adapter/redux_adapter.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export 'adapter.dart';
export 'dynamic_flow_adapter.dart';
export 'recycle_context.dart';
export 'source_flow_adapter.dart';
export 'static_flow_adapter.dart';
Loading

0 comments on commit a134cde

Please sign in to comment.