开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情
一、前言
上一篇文章我们简单实现了一个固定长度的列表,这一篇我们给这个列表加点儿上拉加载和下拉刷新的数据变换.
二、控件状态
当Flutter页面需要动态更新数据时,此时涉及到了UI组件根据数据发生变化,Flutter页面也有了多种状态。之前的Flutter控件提到了无状态组件(StatelessWidget)和有状态组件(StatefulWidget).
很明显,此时我们必须使用StatefulWidget组件了,通过调用setState方法通知界面刷新.有状态组件还可以通过initialState初始化状态.
三、异步 async/await
Android网络编程中对于异步请求,我们可以开启子线程执行耗时任务,主线程和子线程还可以通过handler实现消息通信.Flutter中可以使用async和await.
标记为async的函数返回结果是一个Future包裹的对象,调用方可以使用await从中获取实际返回的数据.在结果没有返回的时候,主线程会执行其他任务.
此时的数据获取还是上节的方式.增加了async方式用来模拟网络请求.
class DynamicMockData {
static Future<List<Map<String, Object>>> list(int page, int size) async {
return List<Map<String, Object>>.generate(size, (index) {
return {
'title': '标题${index + (page - 1) * size + 1}:这是一个列表标题,最多两行,多处部分会被截取',
'imageUrl':
'https://t7.baidu.com/it/u=963301259,1982396977&fm=193&f=GIF',
'viewCount': 20,
};
});
}
}
调用时,使用await获取结果数据.
List<Map<String, Object>> _listItems = await DynamicMockData.list(1, PAGE_SIZE);
四、flutter刷新库
在pubspec.yaml文件中指定刷新库和相应版本号即可,后续执行一下pub get更新一下依赖.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
flutter_easyrefresh: ^2.2.2
五、EasyRefresh
当我们使用EasyRefresh包裹列表组件时,指定onRefresh和onLoad的回调方法,在相应方法里进行数据的获取.
import 'package:fftest1/dynamic_item.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
class TabDynamicPage extends StatefulWidget {
TabDynamicPage({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _TabDynamicPageState();
}
class _TabDynamicPageState extends State<TabDynamicPage> {
static const int PAGE_SIZE = 20;
int _currentPage = 1;
List<Map<String, Object>> _listItems = [];
void _refresh() async {
_currentPage = 1;
_requestNewItems();
}
void _load() async {
_currentPage += 1;
_requestNewItems();
}
void _requestNewItems() async {
List<Map<String, Object>> _newItems =
await DynamicMockData.list(_currentPage, PAGE_SIZE);
this.setState(() {
if (_currentPage > 1) {
_listItems += _newItems;
} else {
_listItems = _newItems;
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: EasyRefresh(
onRefresh: () async {
_refresh();
},
onLoad: () async {
_load();
}, child: ListView.builder(itemCount: _listItems.length,
itemBuilder: (context, index) {
return DynamicItem(_listItems[index]['title'] as String,
_listItems[index]['imageUrl'] as String,
_listItems[index]['viewCount'] as int);
}),
),
);
}
}
- 注:EasyRefresh首次加载的时候不会主动load数据
解决方法
- 1、设置firstRefresh为true
- 2、在initState主动获取数据
@override
void initState() {
// TODO: implement initState
super.initState();
_refresh();
}