fish_redux adapter SourceFlowAdapter 泛型适配器

423 阅读3分钟

制作背景:在使用闲鱼的fish_redux框架的时候就会遇到每次编辑一个列表都需要创建一个adapter适配器,这件事使得我非常的不开心。我就想能不能编写一个能够适配不同page的适配器,接下来就开始思考这个问题。 要实现不同页面的list的适配器就需要根据传入不同page进行适配,使用泛型就非常的适合。 首先我们看到fish_redux的例子里面: 其中page里面有adapter适配器的的链接

adapter: NoneConn<PageState>() + ToDoListAdapter(),

这样我们这个连接器就需要根据传图PageState的不同而进行返回出对应的state。 接下来我们来到adapter连接器的的这个类中。

看到这个类中的PageState,这里的state就固定了类型为PageState,所以我们就需要更改PageStateT(泛型)

class ToDoListAdapter extends SourceFlowAdapter<PageState>class ToDoListAdapter extends SourceFlowAdapter<T>

然后需要把reducerPageState修改为T(泛型)

Reducer<PageState> buildReducer(){
    return asReducer(<Object, Reducer<PageState>>{
      ToDoListAction.add: _add,
      todo_action.ToDoAction.remove: _remove
    });
}
改
Reducer<T> buildReducer(){
    return asReducer(<Object, Reducer<T>>{
      ToDoListAction.add: _add,
      todo_action.ToDoAction.remove: _remove
    });
}

写到这里的时候是不是感觉就OK了? 我发现这个时候这个T(泛型)脚下有个小小的红色波浪线,大吃一惊,然后阅读错误信息

'dynamic' doesn't conform to the bound 'AdapterSource' of the type parameter 'T'. (Documentation)  Try using a type that is or is a subclass of 'AdapterSource'.
The name 'T' isn't a type so it can't be used as a type argument. (Documentation)  Try correcting the name to an existing type, or defining a type named 'T'.

这里告诉我们dynamic类型不是AdapterSource类型,也就是说我们的T(泛型)也不是任意类型都可以使用的,必须是继承了AdapterSource这个类型的T(泛型)才可以使用

然后我开始翻看SourceFlowAdapter这个连接器里面的源码,发现他这个T(泛型)是需要继承AdapterSource这个类型的,所以我们就需要将buildReducer这个方法接收的地方加上继承AdapterSource类的T(泛型),并且MutableSource是继承AdapterSource,我们也可以继承MutableSource

Reducer<T> buildReducer(){
    return asReducer(<Object, Reducer<T>>{
      ToDoListAction.add: _add,
      todo_action.ToDoAction.remove: _remove
    });
}
改
Reducer<T> buildReducer<T extends MutableSource>(){
    return asReducer(<Object, Reducer<T>>{
      ToDoListAction.add: _add,
      todo_action.ToDoAction.remove: _remove
    });
}

然后在看到中间的那两个方法add&remove,看到add这个方法返回的statePageState,这个地方也需要改为T(泛型),同样需要在_add方法上加上继承AdapterSource类的T(泛型)

PageState _add(PageState state, Action action) {
  final ToDoState toDo = action.payload;
  return state.clone()..toDos = (state.toDos.toList()..add(toDo));
}
改
T _add<T extends MutableSource>(T state, Action action) {
  final ToDoState toDo = action.payload;
  return state.clone()..toDos = (state.toDos.toList()..add(toDo));
}

这样的话适配器就算是完成了,修改了几处泛型就解决了每次需要创建adapter适配器的问题 下面是使用方式,无需重复创建adapter适配器,直接在page里面添加adapter即可使用,可以在 这里的泛型是当前pagestate,且当前pagestate也需要继承 MutableSource

adapter: NoneConn<T>() + SourceAdapter(),

编写完毕,下面贴上我的代码

adapter.dart

class SourceAdapter<T extends MutableSource> extends SourceFlowAdapter<T> {
  SourceAdapter()
      : super(
    pool: <String, Component<Object>>{
      "club_item": ClubItemComponent(),
    },
    reducer: tableBuildReducer(),
  );
}

reducer.dart

Reducer<T> tableBuildReducer<T extends MutableSource>() {
  return asReducer(
    <Object, Reducer<T>>{
      SourceAction.action: _source,
    },
  );
}

T _source<T extends MutableSource>(T state, Action action) {
  final T newState = state.clone();
  return newState;
}

action.dart

enum SourceAction { action }

class SourceActionCreator {
  static Action onAction() {
    return const Action(SourceAction.action);
  }
}

page.dart

class ClubPage extends Page<ClubState, Map<String, dynamic>> {
  ClubPage()
      : super(
            initState: initState,
            effect: buildEffect(),
            reducer: buildReducer(),
            view: buildView,
            dependencies: Dependencies<ClubState>(
                adapter: NoneConn<ClubState>() + SourceAdapter(),
                slots: <String, Dependent<ClubState>>{
                }),
            middleware: <Middleware<ClubState>>[
            ],);

}

state.dart

class ClubState extends MutableSource implements Cloneable<ClubState> {

  List<ClubItemState> dataSource = <ClubItemState>[];

  @override
  ClubState clone() {
    return ClubState()..dataSource=dataSource;
  }

  @override
  Object getItemData(int index) {
    return dataSource[index];
  }

  @override
  String getItemType(int index) {
    return "club_item";
  }

  @override
  int get itemCount => dataSource.length ?? 0;

  @override
  void setItemData(int index, Object data) {

  }
}

ClubState initState(Map<String, dynamic> args) {
  return ClubState();
}

总结:将state泛型化能够更好的降低者之间的耦合度,减少代码的冗余,增加复用性,变得不那么僵硬、那么固定化,能够更好的发挥连接器的配置性。