制作背景:在使用闲鱼的fish_redux框架的时候就会遇到每次编辑一个列表都需要创建一个adapter适配器,这件事使得我非常的不开心。我就想能不能编写一个能够适配不同page的适配器,接下来就开始思考这个问题。
要实现不同页面的list的适配器就需要根据传入不同page进行适配,使用泛型就非常的适合。
首先我们看到fish_redux的例子里面:
其中page里面有adapter适配器的的链接
adapter: NoneConn<PageState>() + ToDoListAdapter(),
这样我们这个连接器就需要根据传图PageState的不同而进行返回出对应的state。
接下来我们来到adapter连接器的的这个类中。
看到这个类中的PageState,这里的state就固定了类型为PageState,所以我们就需要更改PageState为T(泛型)
class ToDoListAdapter extends SourceFlowAdapter<PageState>
改
class ToDoListAdapter extends SourceFlowAdapter<T>
然后需要把reducer中PageState修改为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这个方法返回的state是PageState,这个地方也需要改为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即可使用,可以在
这里的泛型是当前page的state,且当前page的state也需要继承 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泛型化能够更好的降低者之间的耦合度,减少代码的冗余,增加复用性,变得不那么僵硬、那么固定化,能够更好的发挥连接器的配置性。