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 给列表增加下拉刷新和上滑加载更多功能

结语

flutter_easyrefresh 可以实现丰富的加载效果,包括自定义加载组件,乃至使用有趣的动画等等,基本上可以满足各类下拉刷新或上滑加载更多的需要。建议可以参考文档多尝试其他效果,有兴趣的也可以阅读源码看看具体的实现方式。

来源:https://juejin.cn/post/6966225049783762980

标签:Flutter,列表,下拉刷新,上拉加载
0
投稿

猜你喜欢

  • Spring依赖注入(DI)两种方式的示例详解

    2021-09-14 12:00:20
  • Java基于递归和循环两种方式实现未知维度集合的笛卡尔积算法示例

    2021-07-19 04:41:18
  • Java回调函数与观察者模式实例代码

    2023-11-16 17:30:11
  • java编程多线程并发处理实例解析

    2022-06-02 22:14:59
  • spring-cloud-gateway动态路由的实现方法

    2021-07-25 15:24:37
  • Android支付宝支付的示例代码

    2022-06-20 02:32:49
  • springboot+gradle 构建多模块项目的步骤

    2023-02-19 00:33:31
  • Android EditText限制输入整数和小数的位数的方法示例

    2022-12-23 05:15:30
  • Java Collection集合iterator方法解析

    2022-11-17 06:43:29
  • Java使用Optional实现优雅避免空指针异常

    2023-06-05 15:35:39
  • 使用ehcache三步搞定springboot缓存的方法示例

    2021-06-25 04:44:12
  • Java内存溢出实现原因及解决方案

    2022-10-19 09:07:42
  • winform实现限制及解除鼠标移动范围的方法

    2023-07-17 22:11:51
  • Android Studio与SVN版本控制程序的协作使用指南

    2021-11-08 15:16:08
  • springBoot系列常用注解(小结)

    2023-12-17 23:26:45
  • Android实现悬浮窗体效果

    2023-03-12 01:04:02
  • 使用Java将一个List运用递归转成树形结构案例

    2021-10-14 15:18:30
  • Android Webview与ScrollView的滚动兼容及留白处理的方法

    2021-09-27 00:56:40
  • C#使用webbrowser的常见用法实例

    2023-06-14 13:57:45
  • Android itemDecoration接口实现吸顶悬浮标题

    2023-03-14 00:58:31
  • asp之家 软件编程 m.aspxhome.com