前言:
Flutter项目需要实现“上拉刷新和分页加载“的功能,分页可以把大量数据分割成一个个小段,分次加载。这样可以有效避免因为一次load全部数据而导致客户端变慢的问题。在这里我使用EasyRefresh第三方插件来实现下拉刷新和分页加载的操作。
用到的知识点:
- dio实现网络请求的数据
- model层封装“上拉刷新和分页加载“的方法
- ui层使用easyrefresh实现下拉刷新,分页加载
- ui层使用listview展示列表信息
实现的步骤:
1.在pubspec.yaml添加sdk
dependencies:
...
cupertino_icons: ^0.1.0
dio: ^2.1.9
scoped_model: ^1.0.1
flutter_easyrefresh: ^1.2.7
2.请求数据
//请求数据的方法
Future getListData(BuildContext context) async {
String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //接口
DioUtil.getInstance().get(context, url).then((res) { //DioUtil是自定义封装网络请求的工具类
if (res.statusCode == Response.ok) {
var responseList = res.data;
if (responseList != null) {
_listData = responseList["loans"];
}
} else {
_listData= [];
}
}).catchError((onError) {
}).whenComplete(this.notifyListeners);
}
3.上拉刷新数据
//上拉刷新数据的方法
Future refreshData(BuildContext context) async {
currentPage = 0;
_listData.clear();
getListData(context);
return null;
}
4.加载更多数据
//加载更多数据的方法
Future loadMoreData(BuildContext context) async {
String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //接口
DioUtil.getInstance().get(context, url).then((res) {
if (res.statusCode == Response.ok) {
var responseList = res.data;
if (responseList != null) {
var listData = responseList["loans"];
currentPage += limit; //每次加载的条数
if (currentPage > 0) {
List list1 = List();
list1.addAll(_listData);
list1.addAll(listData);
_listData= list1;
}
}
} else {
_listData= [];
}
}).catchError((onError) {
}).whenComplete(this.notifyListeners);
}
5.easyrefresh实现下拉刷新,分页加载
Widget _buildListView(BuildContext context, CommonStateModel model) {
return new EasyRefresh(
onRefresh: () => _onListRefresh(context), //下拉刷新
loadMore: () => _onListLoadMore(context), //分页加载更多
key: _easyRefreshKey,
refreshHeader: MaterialHeader( //Material风格的头部刷新
key: _headerKey,
),
refreshFooter: MaterialFooter( //Material风格的底部刷新
key: _footerKey,
),
child: _buildListViewContent(context, model),
);
}
6.listview展示列表信息
Widget _buildListViewContent(BuildContext context, CommonStateModel model) {
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return renderRow(context, model, index);
},
itemCount: model.listData.length,
controller: _scrollController,
);
}
//自定义的列表项
Widget renderRow(BuildContext context, CommonStateModel model, int i) {
var itemData = model.listData[i];
return new InkWell(
child: new Container(
decoration: new BoxDecoration(color: Colors.white),
margin: const EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0),
child: new Row(
children: [
new Expanded(
flex: 1,
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: new Container(
height: 120.0,
child: new Center(
child: Image.asset(images/logo.png),
),
),
)),
new Expanded(
flex: 2,
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: new Column(
children: [
new Text(itemData["name"])
...
],
),
),
),
new Image.asset("images/arrow_right_icon.png",
height: 25.0, width: 25.0)
],
),
),
onTap: () {
//To do something
},
);
}
7.Model层封装“上拉刷新和分页加载“的完整代码
import 'package:scoped_model/scoped_model.dart';
class CommonStateModel extends Model {
int currentPage = 0;
int limit = 4; //每次分页加载的条数
var _listData;
get listData => _listData;
//请求数据的方法
Future getListData(BuildContext context) async {
//接口
String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //接口
DioUtil.getInstance().get(context, url).then((res) { //DioUtil是自定义封装网络请求的工具类
if (res.statusCode == Response.ok) {
var responseList = res.data;
if (responseList != null) {
_listData = responseList["loans"];
}
} else {
_listData= [];
}
}).catchError((onError) {
}).whenComplete(this.notifyListeners);
}
//上拉刷新数据的方法
Future refreshData(BuildContext context) async {
currentPage = 0;
_listData.clear();
getListData(context);
return null;
}
//加载更多数据的方法
Future loadMoreData(BuildContext context) async {
String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //接口
DioUtil.getInstance().get(context, url).then((res) {
if (res.statusCode == Response.ok) {
var responseList = res.data;
if (responseList != null) {
var listData = responseList["loans"];
currentPage += limit; //每次分页加载的条数
if (currentPage > 0) {
List list1 = List();
list1.addAll(_listData);
list1.addAll(listData);
_listData= list1;
}
}
} else {
_listData= [];
}
}).catchError((onError) {
}).whenComplete(this.notifyListeners);
}
static CommonStateModel of(context) =>
ScopedModel.of(context, rebuildOnChange: true);
}
8.UI层实现上拉刷新和分页加载的完整代码
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_easyrefresh/material_header.dart';
import 'package:flutter_easyrefresh/material_footer.dart';
import 'package:scoped_model/scoped_model.dart';
...
class HomePage extends StatefulWidget {
@override
State createState() => HomePageState();
}
class HomePageState extends State
with AutomaticKeepAliveClientMixin {
CommonStateModel commonStateModel;
GlobalKey _easyRefreshKey =
new GlobalKey();
GlobalKey _headerKey =
new GlobalKey();
GlobalKey _footerKey =
new GlobalKey();
ScrollController _scrollController = ScrollController();
_getModel() {
if (commonStateModel == null) {
commonStateModel = CommonStateModel();
}
return commonStateModel;
}
//请求数据的方法
void _initListData(BuildContext context) async {
await commonStateModel.getListData(context);
}
//上拉刷新的方法
Future _onListRefresh(BuildContext context) async {
await commonStateModel.refreshData(context);
}
//分页加载更多的方法
Future _onListLoadMore(BuildContext context) async {
await commonStateModel.loadMoreData(context);
}
@override
void initState() {
super.initState();
_getModel();
_initListData(context);
}
@override
Widget build(BuildContext context) {
super.build(context);
return ScopedModel(
model: commonStateModel,
child: ScopedModelDescendant(
builder: (context, child, model) {
return Scaffold(
body: Container(
decoration: new BoxDecoration(color: Color(0xFFECECEB)),
child: _buildListView(context, model),
),
);
},
),
);
}
//使用easyrefresh实现下拉刷新,分页加载的方法
Widget _buildListView(BuildContext context, CommonStateModel model) {
return new EasyRefresh(
onRefresh: () => _onListRefresh(context),
loadMore: () => _onListLoadMore(context),
key: _easyRefreshKey,
refreshHeader: MaterialHeader( //Material风格的头部刷新
key: _headerKey,
),
refreshFooter: MaterialFooter( //Material风格的底部刷新
key: _footerKey,
),
child: _buildListViewContent(context, model),
);
}
//listview展示列表信息的方法
Widget _buildListViewContent(BuildContext context, CommonStateModel model) {
return ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return renderRow(context, model, index);
},
itemCount: model.listData.length,
controller: _scrollController,
);
}
Widget renderRow(BuildContext context, CommonStateModel model, int i) {
var itemData = model.listData[i];
return new InkWell(
child: new Container(
decoration: new BoxDecoration(color: Colors.white),
margin: const EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 0.0),
child: new Row(
children: [
new Expanded(
flex: 1,
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: new Container(
height: 120.0,
child: new Center(
child: Image.asset(Image.asset(images/logo.png)),
),
),
)),
new Expanded(
flex: 2,
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: new Column(
children: [
new Text[itemData["name"]]
...
],
),
),
),
new Image.asset("images/arrow_right_icon.png",
height: 25.0, width: 25.0)
],
),
),
onTap: () {
//To do something
},
);
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@protected
bool get wantKeepAlive => true;
}
9.总结:
在Flutter项目已经实现”上拉刷新和分页加载“的功能, 如果有什么疑问的话,可以留言联系我哦!