Flutter下拉刷新上拉加载的简单实现方式一

方式一:RefreshIndicator+ListView实现

import 'package:flutter/material.dart';

class SimpleRefreshDemoPage extends StatefulWidget {
  const SimpleRefreshDemoPage({super.key});

  @override
  State<StatefulWidget> createState() {
    return _SimpleRefreshDemoPage();
  }
}

class _SimpleRefreshDemoPage extends State<SimpleRefreshDemoPage> {
  final int pageSize = 50;

  bool disposed = false;

  List<String> dataList = [];

  final ScrollController _scrollController = ScrollController();

  final GlobalKey<RefreshIndicatorState> refreshKey = GlobalKey();

  Future<void> onRefresh() async {
    await Future.delayed(const Duration(seconds: 4));
    dataList.clear();
    for (int i = 0; i < pageSize; i++) {
      dataList.add("refresh");
    }

    if (disposed) {
      return;
    }
    setState(() {});
  }

  Future<void> loadMore() async {
    await Future.delayed(const Duration(seconds: 4));
    for (int i = 0; i < pageSize; i++) {
      dataList.add("loadmore");
    }
    if (disposed) {
      return;
    }
    setState(() {});
  }

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        loadMore();
      }
    });

    Future.delayed(const Duration(seconds: 0), () {
      refreshKey.currentState?.show();
    });
  }

  @override
  void dispose() {
    disposed = true;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("SimpleRefreshDemoPage"),
      ),
      body: RefreshIndicator(
        key: refreshKey,
        onRefresh: onRefresh,
        child: ListView.builder(
          physics: const AlwaysScrollableScrollPhysics(),
          itemBuilder: (context, index) {
            if (index == dataList.length) {
              return Container(
                margin: const EdgeInsets.all(10),
                child: const Align(
                  child: CircularProgressIndicator(),
                ),
              );
            }
            return Card(
              child: Container(
                height: 60,
                alignment: Alignment.centerLeft,
                child: Text("Item ${dataList[index]} $index"),
              ),
            );
          },
          itemCount: (dataList.length >= pageSize)
              ? dataList.length + 1
              : dataList.length,
          controller: _scrollController,
        ),
      ),
    );
  }
}

 如何实现下拉刷新       

 RefreshIndicator

        RefreshIndicator 是 Flutter 中用于实现下拉刷新功能的一个组件。RefreshIndicator 包裹一个可滚动的子组件,如 `ListView` 或 `GridView`,当用户下拉到列表顶部时,会触发刷新操作。上面的例子中RefreshIndicator包裹在了ListView。

        `onRefresh` 是一个返回 `Future` 的异步函数,用于执行刷新操作。

        关键属性

  • onRefresh`: 必须实现的回调函数,定义刷新时的操作。
  • `child`: 需要包裹的可滚动子组件。
  • `color`: 刷新指示器的进度条颜色。
  • `backgroundColor`: 刷新指示器的背景色。
  • `displacement`: 指示器开始显示时与顶部的距离。

如何实现下拉加载

ScrollController

   _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        loadMore();
      }
    });

如何检测用户是否滚动到了 `ScrollView` 的底部?

_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent

_scrollController.position.pixels` :表示当前滚动的位置。

`_scrollController.position.maxScrollExtent` :表示可滚动区域的最大值。

上面两个值相等时,说明用户已经滚动到了底部。

`bool disposed` 字段作用

        在上面的代码中,`bool disposed` 字段用于指示 `State` 对象是否已经被销毁。当 `dispose` 方法被调用时,`disposed` 被设置为 `true`。这个字段主要用于在异步操作完成后,确保不会调用已经被销毁的 `State` 对象的 `setState` 方法。

作用分析

1.防止在销毁后调用 `setState`:
  • 异步操作(如 `Future.delayed`)在完成后,可能会尝试调用 `setState` 来更新 UI。然而,如果在异步操作执行期间,用户已经导航离开了当前页面,导致 `State` 对象被销毁,那么调用 `setState` 就会抛出异常,因为 `State` 已经不再是活动的。
  • 通过检查 `disposed` 字段,可以在调用 `setState` 前确认 `State` 是否仍然有效,从而避免在组件销毁后对其进行不必要的更新。
2.提高代码的稳健性:
  • 这种模式是一种防御性编程的方法,确保应用程序在面对不确定的异步执行时仍然是稳定的。
 @override
  void dispose() {
    disposed = true;
    super.dispose();
  }

  

  Future<void> onRefresh() async {
    await Future.delayed(const Duration(seconds: 4));
    dataList.clear();
    for (int i = 0; i < pageSize; i++) {
      dataList.add("refresh");
    }

    if (disposed) {
      return;
    }
    setState(() {});
  }

  Future<void> loadMore() async {
    await Future.delayed(const Duration(seconds: 4));
    for (int i = 0; i < pageSize; i++) {
      dataList.add("loadmore");
    }
    if (disposed) {
      return;
    }
    setState(() {});
  }

在 `onRefresh` 和 `loadMore` 方法中,`disposed` 被用来检查 `State` 是否已经被销毁。如果 `disposed` 为 `true`,则不再调用 `setState`,从而避免可能的异常。


3.总结


使用 `disposed` 字段可以有效地防止在组件销毁后进行不必要或有害的 UI 更新。这种模式特别适用于涉及异步操作的 Flutter 应用开发,确保代码在处理 `State` 生命周期时更加健壮。

        在 Flutter 中,`dispose` 方法是一个非常重要的生命周期方法,用于在不再需要一个对象时释放资源。通常,`dispose` 方法用于清理那些可能导致内存泄漏的资源,如控制器、监听器和订阅等。

 `dispose` 方法的常规用途

`dispose` 方法在 `StatefulWidget` 的状态对象中被重写。它在以下情况下被调用:

  • Widget 被从树中永久移除时。
  • 需要释放资源以避免内存泄漏时。

`dispose` 方法的典型用法

1.释放控制器:
  • 常用于释放 `AnimationController`、`TextEditingController`、`PageController` 等控制器。
2.取消订阅:
  • 用于取消流(stream)的订阅,以防止内存泄漏。
3.移除监听器:
  • 移除添加到某些对象上的监听器,例如 `ScrollController` 的监听器。

重要注意事项

  • 调用 `super.dispose()`:在重写 `dispose` 方法时,确保在最后调用 `super.dispose()`。这会调用父类的 `dispose` 方法,完成必要的清理。
  • 确保资源释放:所有在 `initState` 或其他地方创建的需要手动管理的资源,都应在 `dispose` 中被正确释放。
  • 流的取消:对于任何流的订阅,一定要在 `dispose` 中调用 `cancel` 方法。

通过正确使用 `dispose` 方法,你可以确保你的应用程序以更高效的方式管理内存,避免可能的内存泄漏问题。

       

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/909579.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB基础介绍以及从0~1语法介绍

目录 MongoDB 教程导读 NoSQL 简介 关系型数据库遵循ACID规则 分布式系统 分布式计算的优点 分布式计算的缺点 什么是NoSQL? 为什么使用NoSQL ? RDBMS vs NoSQL NoSQL 简史 CAP定理&#xff08;CAP theorem&#xff09; NoSQL的优点/缺点 BASE ACID vs BASE N…

Oracle简介、环境搭建和基础DML语句

第一章 ORACLE 简介 1.1 什么是 ORACLE ORACLE数据库系统是美国ORACLE 公司&#xff08;甲骨文&#xff09;提供的以分布式数据库为核心的一组软件产品&#xff0c;是目前最流行的客户/服务器体系结构的数据库之一。 英文官网&#xff1a;Database | Oracle 中文官网&#xff…

前端好用的网站分享——CSS(持续更新中)

1.CSS Scan 点击进入CSS Scan CSS盒子阴影大全 2.渐变背景 点击进入color.oulu 3.CSS简化压缩 点击进入toptal 4.CSS可视化 点击进入CSS可视化 这个强推&#xff0c;话不多说&#xff0c;看图! 5.Marko 点击进入Marko 有很多按钮样式 6.getwaves 点击进入getwaves 生…

黑马官网2024最新前端就业课V8.5笔记---HTML篇

Html 定义 HTML 超文本标记语言——HyperText Markup Language。 标签语法 标签成对出现&#xff0c;中间包裹内容<>里面放英文字母&#xff08;标签名&#xff09;结束标签比开始标签多 /拓展 &#xff1a; 双标签&#xff1a;成对出现的标签 单标签&#xff1a;只有开…

6:arm condition code flags详细的讲解

目录 6.1 arm的 condition code flag 的详细讲解 6.1.1C 6.1.2Z 6.1.3N 6.1.4V 6.1 arm的 condition code flag 的详细讲解 在这篇文章中&#xff0c;我更加严格与严谨的讲解一下 arm的四个condition code flags&#xff0c;因为这个在汇编中还是非常重要的。 6.1.1C 在…

其他节点使用kubectl访问集群,kubeconfig配置文件 详解

上述两种方式&#xff1a;可使用kubectl连接k8s集群。 $HOME/.kube/config 是config文件默认路径&#xff0c;要么直接定义环境变量&#xff0c;要么就直接把文件拷过去 config文件里面&#xff0c;定义了context&#xff0c;里面指定了用户和对应的集群信息&#xff1a; ku…

新世联科技:NG2-A-7在DAC空气捕集提取CO2的应用

一、DAC空气捕集提取CO2的介绍 直接空气碳捕获&#xff08;Direct Air Capture&#xff0c;简称DAC&#xff09;是一种直接从大气中提取二氧化碳的技术。 二、DAC空气捕集提取CO2的前景 从大气中提取的这种二氧化碳可以作为循环经济的一部分以各种不同方式使用。未来&#xf…

十四届蓝桥杯STEMA考试Python真题试卷第二套第五题

来源:十四届蓝桥杯STEMA考试Python真题试卷第二套编程第五题 本题属于迷宫类问题,适合用DFS算法解决,解析中给出了Python中 map() 和列表推导式的应用技巧。最后介绍了DFS算法的两种常见实现方式——递归实现、栈实现,应用场景——迷宫类问题、图的连通性、树的遍历、拓朴排…

js WebAPI黑马笔记(万字速通)

此笔记来自于黑马程序员&#xff0c;pink老师yyds 复习&#xff1a; splice() 方法用于添加或删除数组中的元素。 注意&#xff1a; 这种方法会改变原始数组。 删除数组&#xff1a; splice(起始位置&#xff0c; 删除的个数) 比如&#xff1a;1 let arr [red, green, b…

【C++】踏上C++学习之旅(五):auto、范围for以及nullptr的精彩时刻(C++11)

文章目录 前言1. auto关键字&#xff08;C11&#xff09;1.1 为什么要有auto关键字1.2 auto关键字的使用方式1.3 auto的使用细则1.4 auto不能推导的场景 2. 基于范围的for循环&#xff08;C11&#xff09;2.1 范围for的语法2.2 范围for的使用条件 3. 指针空值nullptr&#xff0…

【Spring】Spring的简单创建和使用

前言 Spring Bean 可以通过两种主要方式定义&#xff1a;基于 XML 配置文件和基于注解。今天我们讲解基于 XML 配置文件‌来定义 Bean &#xff0c;在 XML 配置文件中&#xff0c;使用 <bean> 元素定义 Bean&#xff0c;描述 Bean 的创建、配置和依赖关系&#xff0c;并存…

二次封装 el-pagination 组件存在的问题

在使用 Element Plus 组件时&#xff0c;有时会遇到组件不完全符合需求的情况&#xff0c;这时可能需要对其进行二次封装。在封装 Pagination 组件时&#xff0c;我们会发现一些属性和函数无法正常使用&#xff0c;下面将详细探讨这些问题&#xff0c;并提供一下思路和想法。 …

想唱就唱 2.15.63| 电视免VIP唱K软件,支持手机点歌

想唱就唱是一款实用性强的K歌软件&#xff0c;支持歌曲搜索、歌手搜索及排行榜。软件支持歌曲下载、点歌、插队&#xff0c;还支持手机扫码点歌&#xff0c;功能与KTV软件一致&#xff0c;让用户在家也能享受KTV体验。首次加载较慢&#xff0c;因采用先下载后播放方式。会员版已…

图文深入介绍Oracle DB link(一)

1. 引言&#xff1a; 本文图文深入介绍Oracle DB link&#xff0c;先介绍基本概念。 2.DB link的定义 数据库链接&#xff08;Database Link&#xff0c;简称 DB Link&#xff09;是 Oracle 数据库中的一个重要功能。它是一种在一个 Oracle 数据库实例中访问另一个 Oracle 数…

江协科技STM32学习- P34 I2C通信外设

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

vxe-table 表格中实现多行文本的编辑

Vxe UI vue vxe-table 表格中实现多行文本的编辑 vxe-table v4.8 要在表格中使用多行文本编辑&#xff0c;可以通过设置行高方式&#xff0c;再设置 cell-config.verticalAlign: ‘top’ 单元格垂直对齐方式&#xff0c;实现顶部对齐&#xff0c;因为默认是居中对齐。 代码 …

Linux开发工具——make/Makefile

目录 一、什么是makefile&#xff1f; 二、为什么要有makefile&#xff1f; 三、makefile的使用 1.依赖关系与依赖方法 2.伪目标 3.定义变量 4.特殊符号 四、makefile的执行逻辑 一、什么是makefile&#xff1f; Makefile是一种自动化构建工具&#xff0c;make是一条指…

`掌握Python-PPTX,让PPt制作变得轻而易举!`

文章目录 掌握Python-PPTX&#xff0c;让PPT制作变得轻而易举&#xff01;背景介绍python-pptx 是什么&#xff1f;如何安装 python-pptx&#xff1f;简单库函数使用方法应用场景常见Bug及解决方案总结 掌握Python-PPTX&#xff0c;让PPT制作变得轻而易举&#xff01; 背景介绍…

uniapp vue3 使用echarts-gl 绘画3d图表

我自己翻遍了网上&#xff0c;以及插件市场&#xff0c;其实并没有uniapp 上使用echarts-gl的样例&#xff0c;大多数都是使用插件市场的echarts的插件 开始自己尝试直接用echartsgl 没有成功&#xff0c;后来尝试使用threejs 但是也遇到一些问题&#xff0c;最后我看官网的时…

windows运行ffmpeg的脚本报错:av_ts2str、av_ts2timestr、av_err2str => E0029 C4576

问题描述 我目前的环境是&#xff1a; 编辑器&#xff1a; Microsoft Visual Studio Community 2022 (64 位) 运行的脚本是ffmpeg自带的remux样例&#xff0c;只不过我想用c语言执行这个样例。在执行的过程中报错如下图&#xff1a; C4576 后跟初始值设定项列表的带圆括…