Preface:
The Flutter project needs to realize the function of "pull-up refresh and page loading". The page can divide a large amount of data into small segments and load them in batches. This can effectively avoid the problem that the client slows down due to loading all the data at one time. Here I use the EasyRefresh third-party plug-in to implement the operations of pull-down refresh and paging load.
Knowledge points used:
- dio realizes the data of network request
- The model layer encapsulates the methods of pull-up refresh and paging load
- ui layer uses easyrefresh to realize pull-down refresh and page loading
- ui layer uses listview to display list information
Implementation steps:
1. Add sdk in pubspec.yaml
dependencies: ... cupertino_icons: ^0.1.0 dio: ^2.1.9 scoped_model: ^1.0.1 flutter_easyrefresh: ^1.2.7
2. Request data
//How to request data Future getListData(BuildContext context) async { String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //Interface DioUtil.getInstance().get(context, url).then((res) { //DioUtil is a custom tool class to encapsulate network requests if (res.statusCode == Response.ok) { var responseList = res.data; if (responseList != null) { _listData = responseList["loans"]; } } else { _listData= []; } }).catchError((onError) { }).whenComplete(this.notifyListeners); }
3. Pull up to refresh data
//How to pull up and refresh data Future refreshData(BuildContext context) async { currentPage = 0; _listData.clear(); getListData(context); return null; }
4. Load more data
//How to load more data Future loadMoreData(BuildContext context) async { String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //Interface 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; //Number of entries per load if (currentPage > 0) { List list1 = List(); list1.addAll(_listData); list1.addAll(listData); _listData= list1; } } } else { _listData= []; } }).catchError((onError) { }).whenComplete(this.notifyListeners); }
5.easyrefresh implements pull-down refresh and paging load
Widget _buildListView(BuildContext context, CommonStateModel model) { return new EasyRefresh( onRefresh: () => _onListRefresh(context), //Drop-down refresh loadMore: () => _onListLoadMore(context), //Page load more key: _easyRefreshKey, refreshHeader: MaterialHeader( //Material style head refresh key: _headerKey, ), refreshFooter: MaterialFooter( //Material style bottom refresh key: _footerKey, ), child: _buildListViewContent(context, model), ); }
6.listview display list information
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, ); } //Custom list items Widget renderRow(BuildContext context, CommonStateModel model, int i) { var itemData = model.listData[i]; return new ListTile( title: Text(itemData['name']), onTap: () { launchURL(itemData['url']); }, ); }
7. The model layer encapsulates the complete code of "pull-up refresh and page loading"
import 'package:scoped_model/scoped_model.dart'; class CommonStateModel extends Model { int currentPage = 0; int limit = 4; //Number of entries loaded per page var _listData; get listData => _listData; //How to request data Future getListData(BuildContext context) async { //Interface String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //Interface DioUtil.getInstance().get(context, url).then((res) { //DioUtil is a custom tool class to encapsulate network requests if (res.statusCode == Response.ok) { var responseList = res.data; if (responseList != null) { _listData = responseList["loans"]; } } else { _listData= []; } }).catchError((onError) { }).whenComplete(this.notifyListeners); } //How to pull up and refresh data Future refreshData(BuildContext context) async { currentPage = 0; _listData.clear(); getListData(context); return null; } //How to load more data Future loadMoreData(BuildContext context) async { String url = IHttpService.baseUrl +"&offset=$currentPage&limit=$limit"; //Interface 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; //Number of entries loaded per page 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. The UI layer implements the complete code of pull-up refresh and paging load
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; } //How to request data void _initListData(BuildContext context) async { await commonStateModel.getListData(context); } //Pull up refresh method Future<Null> _onListRefresh(BuildContext context) async { await commonStateModel.refreshData(context); } //More ways to load pages 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), ), ); }, ), ); } //Using easyrefresh to realize pull-down refresh and page loading Widget _buildListView(BuildContext context, CommonStateModel model) { return new EasyRefresh( onRefresh: () => _onListRefresh(context), loadMore: () => _onListLoadMore(context), key: _easyRefreshKey, refreshHeader: MaterialHeader( //Material style head refresh key: _headerKey, ), refreshFooter: MaterialFooter( //Material style bottom refresh key: _footerKey, ), child: _buildListViewContent(context, model), ); } //The method of displaying list information in 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(itemData['logo']), ), ), )), new Expanded( flex: 2, child: new Padding( padding: const EdgeInsets.all(5.0), child: new Column( children: <Widget>[ ... ], ), ), ), 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. summary:
"Pull up refresh and page loading" has been implemented in the Flutter project. If you have any questions, please contact me with a message!