Flutter EasyRefresh+ListView+Scoped Model 實現上拉刷新和分頁加載

前言:網絡

       Flutter項目須要實現「上拉刷新和分頁加載「的功能,分頁能夠把大量數據分割成一個個小段,分次加載。這樣能夠有效避免由於一次load所有數據而致使客戶端變慢的問題。在這裏我使用EasyRefresh第三方插件來實現下拉刷新和分頁加載的操做。async

用到的知識點:ide

  1. dio實現網絡請求的數據
  2. model層封裝「上拉刷新和分頁加載「的方法
  3. ui層使用easyrefresh實現下拉刷新,分頁加載
  4. ui層使用listview展現列表信息

實現的步驟:工具

1.在pubspec.yaml添加sdkflex

dependencies:
  ...
  cupertino_icons: ^0.1.0
  dio: ^2.1.9
  scoped_model: ^1.0.1
  flutter_easyrefresh: ^1.2.7

 2.請求數據ui

//請求數據的方法
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.上拉刷新數據this

//上拉刷新數據的方法
Future refreshData(BuildContext context) async {
    currentPage = 1;
    _listData.clear();
    getListData(context);
    return null;
  }

4.加載更多數據url

//加載更多數據的方法
Future loadMoreData(BuildContext context) async {
    page += 1;//每次加載的條數
    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"];      
            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展現列表信息code

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 = 1;
  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 = 1;
    _listData.clear();
    getListData(context);
    return null;
  }

  //加載更多數據的方法
  Future loadMoreData(BuildContext context) async {
     page += 1;//每次分頁加載的條數
     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"];          
             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項目已經實現」上拉刷新和分頁加載「的功能, 若是有什麼疑問的話,留言聯繫我哦!

相關文章
相關標籤/搜索