Flutter-使用MVP设计模式封装刷新列表组件
前言
在flutter的开发中,经常会遇到ListView
的上下拉加载的业务需求,我也尝试了对该需求的封装,地址https://github.com/zhahao/auto_refresh_list_view.
由于flutter
是响应式的,如果要改变UI的显示,一般会通过修改成员变量的值,再调用setState
方法,让state类
重新调用build
方法.根据成员变量的值返回不同的widget
.AutoRefreshListView
内部封装了RefreshIndicator.child
为ListView.builder()
作为主要widget.通过_state
来控制ListView
显示不同状态的视图.
设计模式
使用MVP的设计模式,将AutoRefreshListView
功能拆分出来以下三个部分,并分别由不同Presenter提供实现.
- 状态视图展示
- 数据的提供
- Item展示
功能实现
AutoRefreshListView内部功能实现
上拉
通过ListView
的ScrollController
来判断
_listScrollController.addListener(() {
var maxScroll = _listScrollController.position.maxScrollExtent;
var pixel = _listScrollController.position.pixels;
if (maxScroll == pixel && _loadingFlag == false) {
/// 先将加载中的flag置为true,防止重复执行上拉逻辑
_loadingFlag = true;
/// 滚动到底了,需要执行上拉操作
}
});
下拉
使用RefreshIndicator.onRefresh
来监听下拉,一旦手指向下拖拽ListView到一定范围,就会触发onRefresh
回调.这个时候一般会去请求网络数据,请求回来之后需要调用setState
,RefreshIndicator会被重新build
,下拉箭头就会消失.
伪代码:
RefreshIndicator(
child: ListView.builder(itemBuilder: null),
onRefresh: () async{
/// 1.请求网络数据
var response = await fetchNetworkData();
/// 2.1如果成功,删除之前的数据缓存并存储请求回来的数据
/// 2.2如果失败,提示失败
if (response.success) {
cleanData();
restoreData();
setState((){});
}else {
showErrorDialog();
}
});
AutoRefreshListView交由Presenter的实现
状态视图展示
使用一个_state
将整个ListView的状态进行记录,一旦_state
发生改变就调用setState
方法.切换build
方法返回的widget
.该功能由RefreshListStateViewIPresenter
提供.
enum _AutoRefreshListViewState {
/// 第一次进入的时候正在加载数据
loadingFirstPage,
/// 第一次进入加载数据失败
errorOnLoadFirstPage,
/// 第一次进入加载数据为空
emptyOnLoadFirstPage,
/// 没有更多数据
loadCompletedNoMoreData,
/// 有更多数据
loadCompletedHasMoreData,
/// 加载更多时失败
errorOnLoadMoreData,
/// 正在加载更多
loadingMoreData,
}
数据的提供
由RefreshListViewDataIPresenter
负责提供,抽象了几个方法,主要包括
- 获取数据
- 清空所有数据,根据需求可重写
- 添加新数据
...
AutoRefreshListView
负责处理RefreshListViewDataIPresenter
和RefreshListStateViewIPresenter
之间的逻辑关系.
Item展示
使用list_view_item_builder三方实现,该库提供了与iOS的UITableview基本一致的delegate
和dataSource
方法.非常方便的构建Listview
的item
.且对该库进行了presenter
处理,由RefreshListViewItemIPresenter
提供item
的实现.
总结
感觉MVP的设计模式在flutter还是可以使用的,提高代码逻辑的复用性.而且dart
支持多继承,那么所有的presenter
都可以使用with
语法聚合在一个类里面实现.这样对于简单的逻辑使用也很方便.