Flutter 给列表增加下拉刷新和上滑加载更多功能
作者:岛上码农 发布时间:2021-10-01 13:30:18
目录
有状态组件
异步 async/await
引入 flutter_easyrefresh
使用 flutter_easyrefresh
运行结果
结语
有状态组件
当 Flutter 的页面需要动态更新数据的时候,就会涉及到 UI 组件需要根据数据变化更新,此时也就意味着组件有了“状态”。这就类似 React 的类组件和函数组件(只是后续 React 使用了勾子函数实现了函数组件也可以有状态)。在 Flutter 中,组件也分为无状态组件(StatelessWidget)和有状态组件(StatefulWidget),一般尽量使用无状态组件。但是如果组件本身需要维护自身状态的时候,就需要使用有状态组件了。有状态组件的定义形式如下:
//有状态组件声明
class DynamicPage extends StatefulWidget {
DynamicPage({Key key}) : super(key: key);
//创建组件状态
@override
_DynamicPageState createState() => _DynamicPageState();
}
//组件状态
class _DynamicPageState extends State<DynamicPage> {
@override
Widget build(BuildContext context) {
//UI 构建
}
}
有状态组件实际的业务逻辑均由对应的状态实现,包括数据定义和 UI 构建。其核心在于有一个 setState 方法用于通知界面刷新(这点也和 React 类似),一旦主动调用了 setState 方法,界面就会进行刷新。当然,其中还有一些别的与状态相关的方法,如状态初始化方法 initialState。
异步 async/await
在网络请求中,不可避免需要用到异步请求,这个时候就需要使用到 async 和 await。标记为 async 的函数返回结果是一个 Future 包裹的对象,调用方可以使用 await 从中获取实际返回的数据。async/await 这个配对就完成了一个异步调用过程。在结果没有返回的时候,主线程会执行其他任务。在这里我们将列表数据获取的方法改为 async 方式,以模拟网络请求,如下所示:
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://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3331308357,177638268&fm=26&gp=0.jpg',
'viewCount': 180,
};
});
}
调用的时候,使用 await即可获取实际结果数据,如下所示:
// _currentPage 为当前页码,PAGE_SIZE为分页大小
List<Map<String, Object>> _newItems =
await DynamicMockData.list(_currentPage, PAGE_SIZE);
引入 flutter_easyrefresh
flutter 需要引入第三方插件时,需要在 pubspec.yaml 文件下的dependencies节点下增加依赖,撰写本文时flutter_easyrefresh的最新版为2.2.1,因此指定版本如下:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_easyrefresh: ^2.2.1
添加完依赖后,需要在项目目录执行 flutter pub get 命令更新依赖(VSCode 在检测到 pubspec.yaml变化时会自动拉取)。
使用 flutter_easyrefresh
对//www.jb51.net/article/213052.htm 上一篇的列表进行改造分为如下三个步骤:
将页面修改为有状态组件,方便支持管理数据和根据数据更新界面
使用 EasyRefresh 包裹列表组件,并指定 onRefresh 和 onLoad 回调方法,以响应下拉刷新和上滑加载更多的动作。
根据当前分页获取数据,并更新到列表数据中,再调用 setState 更新状态数据刷新界面。
整个新的 dynamic_page 的代码如下所示:
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'dynamic_item.dart';
import 'dynamic_mock_data.dart';
class DynamicPage extends StatefulWidget {
DynamicPage({Key key}) : super(key: key);
@override
_DynamicPageState createState() => _DynamicPageState();
}
class _DynamicPageState extends State<DynamicPage> {
List<Map<String, Object>> _listItems = [];
int _currentPage = 1;
static const int PAGE_SIZE = 20;
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'],
_listItems[index]['imageUrl'],
_listItems[index]['viewCount'],
);
}),
),
);
}
}
运行结果
运行结果如下图所示,由于上拉加载过快没法直接截图看到。需要注意的是,首次加载的时候,EasyRefresh 并不会自动加载,这个时候需要使用 EasyRefreshController 来控制,有兴趣的同学可以参考 flutter_easyfresh 的文档实现。
结语
flutter_easyrefresh 可以实现丰富的加载效果,包括自定义加载组件,乃至使用有趣的动画等等,基本上可以满足各类下拉刷新或上滑加载更多的需要。建议可以参考文档多尝试其他效果,有兴趣的也可以阅读源码看看具体的实现方式。
来源:https://juejin.cn/post/6966225049783762980


猜你喜欢
- 时间戳在游戏开发中虽然是一个比较小的功能?但是如果缺少这个功能就会导致开发遇到困难,为了帮助大家开发,下面就给大家介绍下将时间戳的使用方法,
- 什么是jdkjdk是什么呢?jdk的是java development kit的缩写,意思是java程序开发的工具包。也可以说jdk是jav
- 1、Json的制作package com.example.usingjson2; import org.json.
- 实现效果:列出某个目录下的特定后缀名文件(如,列出D盘根目录下txt后缀的文件)import java.io.File;import jav
- 随着市面上越来越多三方APP的出现,某些手机厂商也开始对这些APP进行了安装限制或者运行限制,或者三方APP自身的版本过低,无法被特定的系统
- MapperScan添加动态配置(占位符)在对Mybatis自动扫描配置中,使用注解配置时,@MapperScan中的配置,通常配置如下:@
- 比如要获取打开摄像头的应用程序名称,只需要在frameworks/base/core/android/hardware/Camera.jav
- 目前只实现了java生成的固定的uuid:85bb94b8-fd4b-4e1c-8f49-3cedd49d8f28的序列化package m
- 点九图片的拉伸区域不难理解,显示内容区域是怎样的?.9 ,是andriod平台的应用软件开发里的一种特殊的图片形式,文件扩展名为:.9.pn
- 为了创建比例大小的子View,可以将LinearLayout的宽度和高度设为fill_parent, 而将子View的宽度或是高度设为0,然
- 加锁和解锁我们来看下ReentrantLock的基本用法ThreadDomain35类public class ThreadDomain35
- 需要的Maven<!--redis--> <dependency&g
- shrio是一个比较轻量级的安全框架,主要的作用是在后端承担认证和授权的工作。今天就讲一下shrio进行认证的一个过程。首先先介绍一下在认证
- 引言异步蓝图节点:在蓝图节点的右上角有时钟图标。注意:异步节点可以在EventGraph/Macros中使用,但是无法在蓝图函数中使用。AI
- 效果图如下:默认第一次加载选择原始队列:级联效果图:关键代码给下拉列表选中事件监听绑定Id :int pos = firsthand_dlb
- 最近公司项目中有一个类似滴滴出行填写验证码的弹框,下面是我撸出来的效果: 中间的那个输入密码的6个框框其实就是用shape画的背景
- 本文实例讲述了Android基于TextView属性android:ellipsize实现跑马灯效果的方法。分享给大家供大家参考,具体如下:
- 普通校验导入依赖:默认的报错:没有提示具体的属性设置自己的错误信息提示:创建 ValidationMessages.properties内容
- 本文汇总了高效C#编码常见的优化原则,对于进行C#程序设计来说有很大的参考借鉴作用。具体列出如下:1.foreach VS for 语句Fo
- 本文实例讲述了C#实现发送邮件的三种方法。分享给大家供大家参考。具体方法分析如下:一、问题:最近公司由于一个R&I项目的需要,用户要