Flutter EasyRefresh+ListView+Scoped Model 實現上拉重新整理和分頁載入
阿新 • • 發佈:2019-08-21
前言:
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: <Widget>[
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: <Widget>[
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<CommonStateModel>(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<StatefulWidget> createState() => HomePageState();
}
class HomePageState extends State<HomePage>
with AutomaticKeepAliveClientMixin {
CommonStateModel commonStateModel;
GlobalKey<EasyRefreshState> _easyRefreshKey =
new GlobalKey<EasyRefreshState>();
GlobalKey<RefreshHeaderState> _headerKey =
new GlobalKey<RefreshHeaderState>();
GlobalKey<RefreshFooterState> _footerKey =
new GlobalKey<RefreshFooterState>();
ScrollController _scrollController = ScrollController();
_getModel() {
if (commonStateModel == null) {
commonStateModel = CommonStateModel();
}
return commonStateModel;
}
//請求資料的方法
void _initListData(BuildContext context) async {
await commonStateModel.getListData(context);
}
//上拉重新整理的方法
Future<Null> _onListRefresh(BuildContext context) async {
await commonStateModel.refreshData(context);
}
//分頁載入更多的方法
Future<Null> _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<CommonStateModel>(
model: commonStateModel,
child: ScopedModelDescendant<CommonStateModel>(
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: <Widget>[
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: <Widget>[
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專案已經實現”上拉重新整理和分頁載入“的功能, 如果有什麼疑問的話,可以