
到目前为止,你已经掌握了:
但是一个真实的 App 列表通常需要:
本篇,我们将把这些功能整合成 完整的列表交互示例。
RefreshIndicator(
onRefresh: _refreshData,
child: ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(_items[index]));
},
),
)
📌 功能:
_refreshDataFuture<void> _refreshData() async {
await Future.delayed(Duration(seconds: 2)); // 模拟网络请求
setState(() {
_items = List.generate(20, (index) => '刷新数据 $index');
});
}
📌 RefreshIndicator 只能包裹可滚动组件(ListView / GridView / SingleChildScrollView)
ScrollController _controller = ScrollController();
@override
void initState() {
super.initState();
_controller.addListener(() {
if (_controller.position.pixels == _controller.position.maxScrollExtent) {
_loadMore();
}
});
_refreshData();
}
📌 当滚动到最底部 → 调用 _loadMore() 加载更多数据
Future<void> _loadMore() async {
await Future.delayed(Duration(seconds: 2));
setState(() {
int currentLength = _items.length;
_items.addAll(List.generate(10, (index) => '更多数据 ${currentLength + index}'));
});
}
📌 简单模拟分页加载,真实项目中可结合 page 参数请求 API
class PullLoadListPage extends StatefulWidget {
@override
_PullLoadListPageState createState() => _PullLoadListPageState();
}
class _PullLoadListPageState extends State<PullLoadListPage> {
List<String> _items = [];
ScrollController _controller = ScrollController();
@override
void initState() {
super.initState();
_controller.addListener(() {
if (_controller.position.pixels == _controller.position.maxScrollExtent) {
_loadMore();
}
});
_refreshData();
}
Future<void> _refreshData() async {
await Future.delayed(Duration(seconds: 2));
setState(() {
_items = List.generate(20, (index) => '刷新数据 $index');
});
}
Future<void> _loadMore() async {
await Future.delayed(Duration(seconds: 2));
setState(() {
int currentLength = _items.length;
_items.addAll(List.generate(10, (index) => '更多数据 ${currentLength + index}'));
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('列表分页示例')),
body: RefreshIndicator(
onRefresh: _refreshData,
child: ListView.builder(
controller: _controller,
itemCount: _items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(_items[index]));
},
),
),
);
}
}
📌 功能总结:
_refreshData_loadMoreCircularProgressIndicatorhasMore → 避免重复加载❌ 忘记给 ListView 指定 ScrollController → 上拉监听无效 ❌ setState 内更新列表前没有先判断 mounted → 页面已销毁报错 ❌ 下拉刷新期间又触发上拉 → 数据重复 ❌ 分页数据太大 → 页面卡顿,可使用 ListView.builder 懒加载
你已经学会:
📌 到这里为止:
你的 App 列表功能已经接近真实生产环境水平 ✅
下拉刷新 + 上拉加载 = 完整列表交互 RefreshIndicator + ScrollController + setState 完成动态刷新
《Flutter 零基础入门(四十):TabBar 与底部导航栏 —— 多页面切换与布局技巧》
下一篇我们将学习:
🚀 实现完整多页面 App 框架