问题背景
移动端日常开发过程中,下拉刷新和加载更多是很常见的功能点,现在一起看下flutter是如何实现下拉刷新和加载更多的。
问题分析
1、通过Dio框架获取网络请求
var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$_page";
Response result = await Dio().get(url);
var list = json.decode(result.data)["result"];
2、Flutter中提供了组件 RefreshIndicator用于下拉刷新 其基本的实现方法是在该组件添加onRefresh事件,当用户下拉刷新时会触发该事件,在该事件中可以用调用一个延时任务Future.delayed( ),在延时任务的回调中重新请求数据即可。
RefreshIndicator(
child: ListView.builder(
......
),
// 2、回调下拉刷新事件
onRefresh:this._onRefresh
)
3、flutter中主要通过使用 ListView.builder( ) 添加控制器来实现上拉加载更多
ListView.builder(
// 上拉加载控制器
controller: _scrollController,
itemCount: this._list.length,
itemBuilder: (context,index){
Widget tip = Text("");
// 当渲染到最后一条数据时,加载动画提示
if(index == this._list.length-1){
tip = _getMoreWidget();
}
return Column(
children: <Widget>[
ListTile(
title:Text(
"${this._list[index]["title"]}",
maxLines:1,
)
),
Divider(),
// 加载提示
tip
],
);
},
),
问题解决
上面分析了flutter实现下拉刷新和加载更多的关键环节,完整代码如下:
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
// 页数
int _page = 1;
// 页面数据列表
List _list = [];
// 标志位:是否有更多数据
bool _hasMore = true;
// 滚动控制器
ScrollController _scrollController = new ScrollController();
@override
void initState() {
super.initState();
this._getData();
// 监听滚动事件
_scrollController.addListener((){
if(_scrollController.position.pixels>_scrollController.position.maxScrollExtent-40){
this._getData();
}
});
}
// 获取数据列表
void _getData() async{
if(this._hasMore){
var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$_page";
Response result = await Dio().get(url);
var list = json.decode(result.data)["result"];
setState(() {
// 拼接数据
this._list.addAll(list);
// 页数累加
this._page++;
});
if(list.length<20){
setState(() {
// 关闭加载
this._hasMore = false;
});
}
}
}
// 下拉刷新
Future<void> _onRefresh() async{
print("下拉刷新");
// 持续两秒
await Future.delayed(Duration(milliseconds:2000),(){
// 清空数据进行刷新
this._list.clear();
this._page = 1;
this._getData();
});
}
// 加载动画
Widget _getMoreWidget() {
// 如果还有数据
if(this._hasMore){
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'加载中',
style: TextStyle(fontSize: 16.0),
),
// 加载图标
CircularProgressIndicator(
strokeWidth: 1.0,
)
],
),
),
);
}else{
return Center(
child: Text("...我是有底线的..."),
);
}
}
@override
Widget build(BuildContext context) {
return Container(
child:Scaffold(
appBar: AppBar(
title:Text("新闻列表")
),
body:this._list.length==0?this._getMoreWidget():RefreshIndicator(
child: ListView.builder(
// 上拉加载控制器
controller: _scrollController,
itemCount: this._list.length,
itemBuilder: (context,index){
Widget tip = Text("");
// 当渲染到最后一条数据时,加载动画提示
if(index == this._list.length-1){
tip = _getMoreWidget();
}
return Column(
children: <Widget>[
ListTile(
title:Text(
"${this._list[index]["title"]}",
maxLines:1,
)
),
Divider(),
// 加载提示
tip
],
);
},
),
// 下拉刷新事件
onRefresh:this._onRefresh
)
)
);
}
}
运行结果如下:
问题总结
本文主要是介绍了flutter是如何实现下拉刷新和加载更多的,有兴趣的同学可以进一步深入研究。