实现功能
  1. 支持调用接口调用,分页加载
  2. 支持下拉刷新
效果图

Flutter 实现下拉刷新&上拉加载(包含网络请求)_android

使用方法
  1. 添加依赖
dependencies:
pull_to_refresh: ^1.5.7
dio: 3.0.7
fluttertoast: ^3.1.0

2.主界面

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

import 'ApiServices.dart';
import 'ArticleBeans.dart';
import 'ArticleItem.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ArticleScreen(408),
);
}
}

class ArticleScreen extends StatefulWidget {
final int id;

ArticleScreen(this.id);

@override
State<StatefulWidget> createState() {
return new ArticleScreenState();
}
}

class ArticleScreenState extends State<ArticleScreen>
with AutomaticKeepAliveClientMixin {
List<ArticleBean> _articleList = new List();

ScrollController _scrollController = new ScrollController();

int _page = 1;

RefreshController _refreshController =
new RefreshController(initialRefresh: true);

Future getArticleList() async {
_page = 1;
int _id = widget.id;
apiService.getArticleList((ArticleModel articleModel) {
if (articleModel.isSuccess()) {
_refreshController.refreshCompleted(resetFooterState: true);
setState(() {
_articleList.clear();
_articleList.addAll(articleModel.data.datas);
});
} else {
Fluttertoast.showToast(msg: articleModel.errorMsg);
}
}, (DioError error) {}, _id, _page);
}

Future getMoreArticleList() async {
_page++;
int _id = widget.id;
apiService.getArticleList((ArticleModel articleModel) {
if (articleModel.isSuccess()) {
if (articleModel.data.datas.length > 0) {
_refreshController.loadComplete();
setState(() {
_articleList.addAll(articleModel.data.datas);
});
} else {
_refreshController.loadNoData();
}
} else {
_refreshController.loadFailed();
Fluttertoast.showToast(msg: articleModel.errorMsg);
}
}, (DioError error) {
_refreshController.loadFailed();
}, _id, _page);
}

@override
bool get wantKeepAlive => true;

@override
void dispose() {
_refreshController.dispose();
_scrollController.dispose();
super.dispose();
}

@override
void didChangeDependencies() {
super.didChangeDependencies();
getArticleList();
_scrollController.addListener(() {
/// 滑动到底部,加载更多
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
getMoreArticleList();
}
});
}

@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: SmartRefresher(
enablePullDown: true,
enablePullUp: true,
header: MaterialClassicHeader(),
controller: _refreshController,
onRefresh: getArticleList,
onLoading: getMoreArticleList,
child: ListView.builder(
itemBuilder: itemView,
physics: new AlwaysScrollableScrollPhysics(),
controller: _scrollController,
itemCount: _articleList.length,
),
),
);
}

Widget itemView(BuildContext context, int index) {
return ItemArticleList(item: _articleList[index]);
}
}

3.单行item

import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';

import 'ArticleBeans.dart';

class ItemArticleList extends StatefulWidget {
ArticleBean item;

ItemArticleList({this.item});

@override
State<StatefulWidget> createState() {
return new ItemArticleListState();
}
}

class ItemArticleListState extends State<ItemArticleList> {
@override
Widget build(BuildContext context) {
var item = widget.item;
return InkWell(
onTap: () {
Fluttertoast.showToast(msg: item.title);
},
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(16, 10, 16, 10),
child: Row(
children: <Widget>[
Expanded(
child: Text(
item.title,
maxLines: 2,
style: TextStyle(
fontSize: 16,
),
textAlign: TextAlign.left,
),
)
],
),
),
Divider(height: 1),
],
),
);
}

}

  1. 网络请求
import 'package:dio/dio.dart';

import 'ArticleBeans.dart';

ApiService _apiService = new ApiService();

ApiService get apiService => _apiService;

class ApiService {
Dio dio = Dio();

/// 获取公众号文章列表数据
void getArticleList(
Function callback, Function errorCallback, int _id, int _page) async {
String baseUrl = "https://www.wanandroid.com/wxarticle/list";
dio.get(baseUrl + "/$_id/$_page/json").then((response) {
callback(ArticleModel.fromJson(response.data));
}).catchError((e) {
errorCallback(e);
});
}
}