Flutter笔记:滚动之-无限滚动与动态加载的实现(GetX简单状态管理版)

Flutter笔记
无限滚动与动态加载的实现
(GeX简单状态管理版)

作者李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/133365040

GetX简单状态管理提供了一种更高效的且用于取代Flutter有状态组件(StatefullWidget)的方式。本文是《无限滚动与动态加载的实现》(地址:https://jclee95.blog.csdn.net/article/details/133340592)的另外一个版本,抛弃了Flutter有状态组件,取而代之的是GetX简单状态管理。以GetX简单状态管理的方式实现的。基本过程和思路一样,仅仅是状态管理方式上不一样。另外对于部分效果进行了简单的改进。



1. 无限滚动列表

在 Flutter 中,实现一个无尽滚动列表通常涉及使用 ListView、ListView.builder 或 ListView.separated 组件,并结合数据源和滚动控制器。这使得您可以加载和显示大量数据,只有在需要时才会动态加载更多数据,以实现无尽滚动效果。

2. 模拟滚动列表的基本实现举例(ListView.builder)

2.1 实现思路与步骤介绍

以下是实现 Flutter 无尽滚动列表的一般步骤:

准备数据源

首先需要有一个数据源。比如一个列表或一个数据库查询结果,或者是网络请求的数据,以供列表渲染。通常,这些数据应该是 按需加载 的,而不是一次性加载所有数据。

创建滚动控制器

通过 ScrollController 创建一个滚动控制器,以便监听列表的滚动事件。这将帮助您确定何时加载更多数据。

构建列表视图

使用 ListView.builder 构建一个列表视图,该构造函数会创建一个只渲染可见项的列表。通过指定 itemBuilder 参数来定义如何渲染每个列表项。

设置滚动监听

将滚动控制器添加到列表视图,并使用 addListener 监听滚动事件。当用户滚动列表时,可以在适当的时候触发加载更多数据的操作。

加载更多数据

在需要加载更多数据时,您可以调用数据源的方法或请求数据。这可以是从网络获取数据、从本地数据库查询数据或其他方式。一旦数据准备好,将其添加到数据源中,然后通知列表视图重新构建。

更新列表视图

当有新数据可用时,调用 setState 方法以通知 Flutter 重新构建列表视图。这将导致列表视图加载和显示新数据。

2.2 一个简单例子

依据 2.1 小节的步骤,实现一个模拟无线滚动的例子如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);Widget build(BuildContext context) {return const MaterialApp(home: InfiniteScrollList(),);}
}class Controller extends GetxController {ScrollController scrollController = ScrollController();List<String> items = <String>[];var isLoading = false;void loadMore() {if (scrollController.position.pixels ==scrollController.position.maxScrollExtent &&!isLoading) {isLoading = true;update();// 模拟加载1秒延时Future.delayed(const Duration(seconds: 1), () {// 生成3项假数据插入items.addAll(List.generate(3, (index) => 'Item ${index + items.length}'));isLoading = false;update();});}}static Controller get to => Get.find();void onInit() {// 初始化一些数据items = List.generate(20, (index) => 'Item $index');scrollController = ScrollController();isLoading = false;// 添加滚动监听器scrollController.addListener(loadMore);super.onInit();}void onClose() {scrollController.dispose();super.onClose();}
}class InfiniteScrollList extends StatelessWidget {const InfiniteScrollList({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('无尽滚动列表'),),body: GetBuilder<Controller>(init: Controller(),builder: (controller) {return Column(children: [Expanded(child: ListView.builder(controller: controller.scrollController,itemCount:controller.items.length + (controller.isLoading ? 1 : 0),itemBuilder: (context, index) {if (index < controller.items.length) {return Card(elevation: 3,margin: const EdgeInsets.all(8),child: ListTile(title: Text(controller.items[index]),// 在这里添加商品卡片的内容// 例如:商品图片、描述、价格等),);} else {return const Padding(padding: EdgeInsets.all(12.0),child: Center(child: SizedBox(width: 18.0,height: 18.0,child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation<Color>(Colors.grey,), // 颜色为灰色strokeWidth: 3, // 线宽为3),),),);}},),),],);},),);}
}

上面的代码中,InfiniteScrollList 是一个 StatefulWidget,它包含了一个可无限滚动的列表视图,可以自动加载更多数据。首先,初始状态下,列表包含20个整数项。当用户滚动到列表的底部时,它会模拟加载更多数据,每次加载三个(生成的假数据)。当加载更多数据时,会显示一个加载指示器。效果如图所示:

在这里插入图片描述

通过这些步骤,可以实现一个无限滚动列表,用户可以滚动并加载更多数据,从而创建无限滚动的体验。这对于需要显示大量数据的应用程序非常有用,例如社交媒体新闻源或产品列表。

这个代码实现了一个无限滚动的列表,其中使用了GetX来进行简单的状态管理。以下是对这个代码实现无限滚动的解释:

  1. 创建一个Controller类,该类继承自GetxController,用于管理状态和滚动。
class Controller extends GetxController {ScrollController scrollController = ScrollController();List<String> items = <String>[];var isLoading = false;// 省略了其它方法
}
  • scrollController 用于管理列表的滚动。
  • items 用于存储列表中的数据项。
  • isLoading 用于标识是否正在加载更多数据。
  1. Controller类中定义了一个名为loadMore的方法,该方法用于检测是否需要加载更多数据。
void loadMore() {if (scrollController.position.pixels ==scrollController.position.maxScrollExtent &&!isLoading) {isLoading = true;update();// 模拟加载1秒延时Future.delayed(const Duration(seconds: 1), () {// 生成3项假数据插入items.addAll(List.generate(3, (index) => 'Item ${index + items.length}'));isLoading = false;update();});}
}
  • loadMore 方法会在滚动到列表底部且不处于加载状态时触发。
  • 在加载数据时,它模拟了1秒的延时,然后生成3个假数据项,将它们添加到 items 列表中。
  • 加载完成后,将 isLoading 设置为 false 并调用 update 方法通知界面更新。
  1. Controller类的onInit方法中初始化了一些数据,并为scrollController添加了滚动监听器。

void onInit() {// 初始化一些数据items = List.generate(20, (index) => 'Item $index');scrollController = ScrollController();isLoading = false;// 添加滚动监听器scrollController.addListener(loadMore);super.onInit();
}
  • 在初始化时,生成了20个假数据项并将它们存储在 items 列表中。
  • 创建了 scrollController 并将滚动监听器 loadMore 添加到它上面。
  1. InfiniteScrollList小部件中使用了 GetBuilder,它监听 Controller 的状态变化并更新UI。
body: GetBuilder<Controller>(init: Controller(),builder: (controller) {return Column(children: [Expanded(child: ListView.builder(controller: controller.scrollController,itemCount: controller.items.length + (controller.isLoading ? 1 : 0),itemBuilder: (context, index) {if (index < controller.items.length) {// 渲染数据项} else {// 渲染加载指示器}},),),],);},
),
  • GetBuilder 会监听 Controller 的状态变化,包括 itemsisLoading,以便在数据加载时更新UI。
  • ListView.builder 用于构建列表,它的 itemCount 根据数据项的数量和加载状态动态确定。
  • itemBuilder 中,根据索引渲染数据项或加载指示器。

总结:这个代码通过GetX库实现了一个无限滚动的列表,可以动态加载数据。滚动到列表底部时,它会触发加载更多数据的操作,加载完成后更新UI以显示新的数据项。GetX的简单状态管理使得管理状态变得更加容易。

3. 改造1:仿淘宝无线滚动网格基本实现举例(GridView.builder)

基本原理与无线滚动的列表类似,要改造为模拟无限滚动的 GridView需要进行的步骤包括:

  1. 创建数据源:首先,您需要准备一个数据源,这可以是一个包含商品信息的列表。
  2. 创建滚动视图:替换 ListView.builder 为 GridView.builder,以创建网格视图。设置 gridDelegate 来指定列数和布局。
  3. 滚动监听:使用 ScrollController 监听滚动事件,类似于之前的示例,以确定何时触发加载更多数据的操作。
  4. 动态加载触发:在滚动监听器中,检查滚动位置是否接近底部,如果是,触发加载更多数据的操作。
  5. 更新数据源:当触发加载更多数据时,更新数据源,通常是从网络或其他数据源获取新数据,并将其添加到数据源中。
  6. 重新构建UI:使用 setState() 来通知 Flutter 重新构建 UI,以显示新加载的数据。

具体的实现代码如下:

import 'package:flutter/material.dart';
import 'package:get/get.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);Widget build(BuildContext context) {return const MaterialApp(home: InfiniteScrollGrid(),);}
}class Controller extends GetxController {ScrollController scrollController = ScrollController();List<String> items = <String>[];var isLoading = false;void loadMore() {if (scrollController.position.pixels ==scrollController.position.maxScrollExtent &&!isLoading) {isLoading = true;update();// 模拟加载1秒延时Future.delayed(const Duration(seconds: 1), () {// 生成3项假数据插入items.addAll(List.generate(3, (index) => 'Item ${index + items.length}'));isLoading = false;update();});}}static Controller get to => Get.find();void onInit() {// 初始化一些数据items = List.generate(20, (index) => 'Item $index');scrollController = ScrollController();isLoading = false;// 添加滚动监听器scrollController.addListener(loadMore);super.onInit();}void onClose() {scrollController.dispose();super.onClose();}
}class InfiniteScrollGrid extends StatelessWidget {const InfiniteScrollGrid({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('无尽滚动网格'),),body: GetBuilder<Controller>(init: Controller(),builder: (controller) {return Column(children: [Expanded(child: GridView.builder(controller: controller.scrollController,gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, // 列数childAspectRatio: 0.7, // 网格项的宽高比),itemCount: controller.items.length,itemBuilder: (context, index) {return Card(elevation: 3,margin: const EdgeInsets.all(8),child: Text(controller.items[index]),);},),),if (controller.isLoading)const Padding(padding: EdgeInsets.all(12.0),child: Center(child: SizedBox(width: 18.0,height: 18.0,child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation<Color>(Colors.grey,), // 颜色为灰色strokeWidth: 3, // 线宽为3),),),),],);},),);}
}

这段代码的实现效果为:

在这里插入图片描述

import 'package:flutter/material.dart';
import 'package:get/get.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);Widget build(BuildContext context) {return const MaterialApp(home: InfiniteScrollGrid(),);}
}class Controller extends GetxController {ScrollController scrollController = ScrollController();List<String> items = <String>[];var isLoading = false;void loadMore() {if (scrollController.position.pixels ==scrollController.position.maxScrollExtent &&!isLoading) {isLoading = true;update();// 模拟加载1秒延时Future.delayed(const Duration(seconds: 1), () {// 生成3项假数据插入items.addAll(List.generate(3, (index) => 'Item ${index + items.length}'));isLoading = false;update();});}}static Controller get to => Get.find();void onInit() {// 初始化一些数据items = List.generate(20, (index) => 'Item $index');scrollController = ScrollController();isLoading = false;// 添加滚动监听器scrollController.addListener(loadMore);super.onInit();}void onClose() {scrollController.dispose();super.onClose();}
}class InfiniteScrollGrid extends StatelessWidget {const InfiniteScrollGrid({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('无尽滚动网格'),),body: GetBuilder<Controller>(init: Controller(),builder: (controller) {return Column(children: [Expanded(child: GridView.builder(controller: controller.scrollController,gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, // 列数childAspectRatio: 0.7, // 网格项的宽高比),itemCount: controller.items.length,itemBuilder: (context, index) {return Card(elevation: 3,margin: const EdgeInsets.all(8),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [// 商品图片Image.network('https://csdn-ebook-resources.oss-cn-beijing.aliyuncs.com/images/4e05b89fedf043f1964e73aa729d21fb/cover.jpg',width: double.infinity, // 图片宽度占满卡片宽度height: 200, // 图片高度fit: BoxFit.cover, // 图片填充方式),// 商品名称const Padding(padding: EdgeInsets.all(8.0),child: Text('商品名称',style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),),),// 商品描述const Padding(padding: EdgeInsets.all(8.0),child: Text('商品描述',style: TextStyle(fontSize: 16),),),// 商品价格const Padding(padding: EdgeInsets.all(8.0),child: Text('¥ 99.99',style: TextStyle(fontSize: 18, color: Colors.red),),),// 在这里添加其他商品信息],),);},),),if (controller.isLoading)const Padding(padding: EdgeInsets.all(12.0),child: Center(child: SizedBox(width: 18.0,height: 18.0,child: CircularProgressIndicator(valueColor: AlwaysStoppedAnimation<Color>(Colors.grey,), // 颜色为灰色strokeWidth: 3, // 线宽为3),),),),],);},),);}
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

阿里云RDS关系型数据库详细介绍_多版本数据库说明

阿里云RDS关系型数据库大全&#xff0c;关系型数据库包括MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等&#xff0c;NoSQL数据库如Redis、Tair、Lindorm和MongoDB&#xff0c;阿里云百科分享阿里云RDS关系型数据库大全&#xff1a; 目录 阿里云RDS关系型数据库大全 …

通过containerd部署k8s集群环境及初始化时部分报错解决

目录 一.基础环境配置&#xff08;每个节点都做&#xff09; 1.hosts解析 2.防火墙和selinux 3.安装基本软件并配置时间同步 4.禁用swap分区 5.更改内核参数 6.配置ipvs 7.k8s下载 &#xff08;1&#xff09;配置镜像下载相关软件 &#xff08;2&#xff09;配置kube…

【视频去噪】基于全变异正则化最小二乘反卷积是最标准的图像处理、视频去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

stl格式-3D三角形

文章目录 什么是stl文件?格式首选stl的语法1.这是一个stl格式的文件:(ASCII码)2.下面先举个例子(难度略微提示)补充:关于\<\<我试了一下:这个法线你随便写好像也没问题\>> 3.来个立方体4.最后再写一个由三个直角形组成的立方体(直棱锥)5.amend 修正(右手定则,法线…

毛玻璃态计算器

效果展示 页面结构组成 从上述的效果可以看出&#xff0c;计算机的页面比较规整&#xff0c;适合grid布局。 CSS3 知识点 grid 布局 实现计算机布局 <div class"container"><form class"calculator" name"calc"><input type…

EasyEdge 智能边缘控制台通过sdk发布应用

离线部署SDK生成 模型部署完成后会出现下载SDK的按钮&#xff0c;点击按钮下载SDK并保存好SDK。 进入EasyDL官网的技术文档 安装智能边缘控制台 跟着教程&#xff0c;完成安装&#xff1a;点此链接 树莓派4b是Linux arm64的架构&#xff0c;点击对应的链接进行下载。 下载完成…

金融帝国实验室(CapLab)官方更新_V9.1.15版本(2023年第64次)

〖金融帝国实验室〗&#xff08;Capitalism Lab&#xff09;游戏更新记录&#xff08;2023年度&#xff09; ————————————— ◎游戏开发&#xff1a;Enlight Software Ltd.&#xff08;微启软件有限公司&#xff09; ◎官方网站&#xff1a;https://www.capitalis…

阿里云通义千问14B模型开源!性能超越Llama2等同等尺寸模型

9月25日&#xff0c;阿里云开源通义千问140亿参数模型Qwen-14B及其对话模型Qwen-14B-Chat,免费可商用。Qwen-14B在多个权威评测中超越同等规模模型&#xff0c;部分指标甚至接近Llama2-70B。阿里云此前开源了70亿参数模型Qwen-7B等&#xff0c;一个多月下载量破100万&#xff0…

【C++】笔试训练(三)

目录 一、选择题二、编程题1、字符串中找出连续最长的数字串2、数组中出现次数超过一半的数字 一、选择题 1、以下程序的输出结果是&#xff08;&#xff09; #include <stdio.h> int main() {char a[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, * p;int i;i 8;p a i;p…

IO流之File类

File类 File 对应的硬盘上的文件或者文件夹 位于java.io包下 File对文件/文件夹进行操作&#xff0c;但是无法对文件内容进行操作&#xff0c;读取/写入不可以操作&#xff0c;但是可以创文件夹/读取文件路径,IO流才可以进行操作 文件/文件夹的路径&#xff1a;linux使用/作为文…

【红外与可见光图像融合】离散平稳小波变换域中基于离散余弦变换和局部空间频率的红外与视觉图像融合方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

音频编辑软件Steinberg SpectraLayers Pro mac中文软件介绍

Steinberg SpectraLayers Pro mac是一款专业的音频编辑软件&#xff0c;旨在帮助音频专业人士进行精细的音频编辑和声音处理。它提供了强大的频谱编辑功能&#xff0c;可以对音频文件进行深入的频谱分析和编辑。 Steinberg SpectraLayers Pro mac软件特点 1. 频谱编辑&#xff…

基于SpringBoot的知识管理系统

目录 前言 一、技术栈 二、系统功能介绍 用户管理 文章分类 资料分类 文章信息 论坛交流 资料下载 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个…

Windows历史版本下载

1、微PE工具箱&#xff08;非广告本人常用&#xff09; 常用安装Windows系统的微PE工具 地址&#xff1a;https://www.wepe.com.cn/download.html 2、Windows系统下载地址&#xff08;非微软官方&#xff09; 地址&#xff1a;MSDN, 我告诉你 - 做一个安静的工具站 下载&…

SpringMVC的请求映射:路由请求的精准导航

SpringMVC的请求映射&#xff1a;路由请求的精准导航 SpringMVC是一个用于构建Web应用程序的强大框架&#xff0c;它提供了众多的特性和组件来简化开发过程。其中&#xff0c;请求映射是SpringMVC中的一个关键特性&#xff0c;用于将HTTP请求映射到具体的处理方法。本文将深入…

RocketMQ Dashboard说解

RocketMQ Dashboard 是 RocketMQ 的管控利器&#xff0c;为用户提供客户端和应用程序的各种事件、性能的统计信息&#xff0c;支持以可视化工具代替 Topic 配置、Broker 管理等命令行操作。 介绍​ 功能概览​ 面板功能运维修改nameserver 地址; 选用 VIPChannel驾驶舱查看 …

基于SpringBoot的高校学科竞赛平台

目录 前言 一、技术栈 二、系统功能介绍 竞赛题库管理 竞赛信息管理 晋级名单管理 往年成绩管理 参赛申请管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步…

【信创】麒麟v10(arm)-mysql8-mongo-redis-oceanbase

Win10/Win11 借助qume模拟器安装arm64麒麟v10 前言 近两年的国产化进程一直在推进&#xff0c;基于arm架构的国产系统也在积极发展&#xff0c;这里记录一下基于麒麟v10arm版安装常见数据库的方案。 麒麟软件介绍: 银河麒麟高级服务器操作系统V10 - 国产操作系统、银河麒麟、中…

redis解压+windows安装+无法启动:1067

Redis下载安装图文教程&#xff08;Windows版_超详细&#xff09; 标题若遇到安装后无法启动&#xff1a;1067 排查方法如下&#xff1a; 1.查询是否有服务占用端口 查看6379的端口也没有被占用&#xff08;netstat -ano | findstr :6379&#xff09; 若有&#xff0c;kill掉…