实现下拉刷新
- flutter中,已经给出了实现,咱们只需要给出回调即可。
- 很多解释都在注释中,请不要忽略。
- 如果你想要直接看到全部代码,请拉到最后。
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_demo/base/view.dart';
import 'package:flutter_demo/common/my_flutter_toast/MyToast.dart';
import 'package:flutter_demo/common/my_flutter_toast/ToastType.dart';
import 'package:flutter_demo/view/news/NewsItem.dart';
import 'Model.dart';
class NewsPage extends StatefulWidget {
@override
_NewsPageState createState() => _NewsPageState();
}
class _NewsPageState extends State<NewsPage> {
List _goodsList = [];
int _currentPage = 1;
int _pageSize = 15;
//数据是否全部加载完毕
bool _isOver = false;
@override
void initState() {
// TODO: implement initState
super.initState();
this._initData();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
// 封装的工具方法,如果使用请修改为正常写法
appBar: getAppBar('News Center'),
body: RefreshIndicator(
onRefresh: () async {
// 这里写下拉刷新后执行的代码
print(1);
},
child: ListView.builder(
itemBuilder: _builder,
itemCount: this._goodsList.length,
)),
);
}
Widget _builder(BuildContext context, int index) {
return NewsItem(Goods(
this._goodsList[index]['title'],
this._goodsList[index]['id'],
this._goodsList[index]['price'],
this._goodsList[index]['category'],
));
}
/*
获取数据
*/
_loadData() async {
//请自行写一个接口,或者使用定时器来模拟
final Response res = await Dio().get(
'http://localhost:3000/flutter?page=${this._currentPage}&pageSize=${this._pageSize}');
//请求成功或再做处理
if (res.statusCode == 200 && res.data['success'] == true) {
//不要忘记赋值操作要在这个函数中
setState(() {
//如果该次请求的数据量小于每页的最大数据量,则判断为全部加载完毕
if (res.data['result'].length < this._pageSize) {
this._isOver = true;
}
//当前的页数要加1
this._currentPage++;
this._goodsList.addAll(res.data['result']);
});
}
}
//首次加载有loading提示
_initData() async {
Timer(Duration.zero, () {
MyToast.showToast(
context: context, type: ToastType.loading, message: '正在加载');
});
await this._loadData();
MyToast.hideToast(context);
}
}
RefreshIndicator 该组件即为flutter实现的下拉刷新组件,它有一个必需参数为onRefresh ,接收一个Future 类型的函数。你可以在下拉后进行一些异步操作。
实现上滑加载
在完成了下拉刷新的基础上,我们需要借用ScrollController 来判断页面滚动条是否拉到底部,从而请求数据。
- 在类中声明变量
ScrollController _scrollController = ScrollController(); - 在
ListView 中添加一条参数controller: this._scrollController, - 在
initState() 中注册监听
this._scrollController.addListener(() async {
//滑到底部时触发
if (this._scrollController.position.pixels >=
this._scrollController.position.maxScrollExtent) {
if (!this._isOver) {
this._loadData();
}
}
});
- 补充上一条,如果你足够细心,会发现此种写法在你上滑到底部时,触发多次,这就需要节流操作。如下所示,这样的作用为在100ms内,若多次触发了"上滑到底部"这个事件,网络请求也只会发出一次。注意在类中声明变量
Timer? _timer;
this._scrollController.addListener(() async {
//滑到底部时触发
if (this._scrollController.position.pixels >=
this._scrollController.position.maxScrollExtent) {
if (!this._isOver) {
//节流
if (this._timer != null) this._timer!.cancel();
this._timer = Timer(Duration(milliseconds: 100), () {
this._loadData();
});
}
}
});
- 最后,在组件销毁时,要将
_scrollController 销毁。
@override
void dispose() {
// TODO: implement dispose
super.dispose();
this._scrollController.dispose();
}
全部代码
主要实现页
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_demo/base/view.dart';
import 'package:flutter_demo/common/my_flutter_toast/MyToast.dart';
import 'package:flutter_demo/common/my_flutter_toast/ToastType.dart';
import 'package:flutter_demo/view/news/NewsItem.dart';
import 'Model.dart';
class NewsPage extends StatefulWidget {
@override
_NewsPageState createState() => _NewsPageState();
}
class _NewsPageState extends State<NewsPage> {
ScrollController _scrollController = ScrollController();
List _goodsList = [];
int _currentPage = 1;
int _pageSize = 15;
bool _isOver = false;
//节流阀
Timer? _timer;
@override
void initState() {
// TODO: implement initState
super.initState();
this._initData();
this._scrollController.addListener(() async {
//滑到底部时触发
if (this._scrollController.position.pixels >=
this._scrollController.position.maxScrollExtent) {
if (!this._isOver) {
//节流
if (this._timer != null) this._timer!.cancel();
this._timer = Timer(Duration(milliseconds: 100), () {
this._loadData();
});
}
}
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
this._scrollController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: getAppBar('News Center'),
body: RefreshIndicator(
onRefresh: () async {
print(1);
},
child: ListView.builder(
itemBuilder: _builder,
itemCount: this._goodsList.length,
controller: this._scrollController,
)),
);
}
Widget _builder(BuildContext context, int index) {
return NewsItem(Goods(
this._goodsList[index]['title'],
this._goodsList[index]['id'],
this._goodsList[index]['price'],
this._goodsList[index]['category'],
));
}
/*
获取数据
*/
_loadData() async {
final Response res = await Dio().get(
'http://localhost:3000/flutter?page=${this._currentPage}&pageSize=${this._pageSize}');
if (res.statusCode == 200 && res.data['success'] == true) {
setState(() {
if (res.data['result'].length < this._pageSize) {
this._isOver = true;
}
this._currentPage++;
this._goodsList.addAll(res.data['result']);
});
}
}
//首次加载有loading提示
_initData() async {
Timer(Duration.zero, () {
MyToast.showToast(
context: context, type: ToastType.loading, message: '正在加载');
});
await this._loadData();
MyToast.hideToast(context);
}
}
子组件
import 'package:flutter/material.dart';
import 'Model.dart';
class NewsItem extends StatelessWidget {
final Goods _item;
NewsItem(this._item);
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(this._item.title),
subtitle: Text(
'分类ID:${this._item.category} 价格:¥${this._item.price} 商品ID:${this._item.id}'));
}
}
数据模型
class Goods {
String title;
int id;
double price;
int category;
Goods(this.title, this.id, this.price, this.category);
}
求赞!
|