flutter ListView 局部刷新

news2025/2/13 0:12:56

在 Flutter 中,要仅刷新 ListView 中的某一列(即特定列表项),可以通过以下步骤实现:


核心思路

  1. 为每个列表项分配唯一标识(如 Key),帮助 Flutter 识别需要更新的项。

  2. 局部状态管理:通过 StatefulWidget 或状态管理工具(如 ProviderBloc)控制单个列表项的更新。

  3. 避免全局刷新:不调用 setState() 刷新整个列表,而是仅更新目标项。


方法 1:使用 StatefulWidget + Key

为每个列表项包裹 StatefulWidget,并为其分配唯一 Key。当数据变化时,仅触发目标项的 setState

class MyListView extends StatelessWidget {
  final List<String> items = List.generate(20, (i) => 'Item $i');

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) => ListItem(
        key: ValueKey(items[index]), // 唯一 Key
        content: items[index],
      ),
    );
  }
}

class ListItem extends StatefulWidget {
  final String content;

  const ListItem({Key? key, required this.content}) : super(key: key);

  @override
  _ListItemState createState() => _ListItemState();
}

class _ListItemState extends State<ListItem> {
  bool _isSelected = false;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(widget.content),
      trailing: _isSelected ? Icon(Icons.check) : null,
      onTap: () {
        // 仅更新当前列表项
        setState(() => _isSelected = !_isSelected);
      },
    );
  }
}

方法 2:使用 Provider 状态管理

通过 ChangeNotifier 管理数据,结合 Consumer 或 Selector 实现局部刷新。

步骤 1:定义数据模型
class ItemModel extends ChangeNotifier {
  final List<Item> _items = List.generate(20, (i) => Item(id: i, text: 'Item $i'));

  List<Item> get items => _items;

  void toggleSelection(int id) {
    final item = _items.firstWhere((item) => item.id == id);
    item.isSelected = !item.isSelected;
    notifyListeners(); // 通知监听者
  }
}

class Item {
  final int id;
  final String text;
  bool isSelected;

  Item({required this.id, required this.text, this.isSelected = false});
}
步骤 2:在顶层提供 Model
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => ItemModel(),
      child: MyApp(),
    ),
  );
}
步骤 3:构建 ListView 并局部刷新
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Consumer<ItemModel>(
          builder: (context, model, child) {
            return ListView.builder(
              itemCount: model.items.length,
              itemBuilder: (context, index) {
                final item = model.items[index];
                // 使用 Selector 优化,仅在 item.isSelected 变化时刷新
                return Selector<ItemModel, bool>(
                  selector: (_, model) => model.items[index].isSelected,
                  builder: (_, isSelected, __) {
                    return ListTile(
                      title: Text(item.text),
                      trailing: isSelected ? Icon(Icons.check) : null,
                      onTap: () => model.toggleSelection(item.id),
                    );
                  },
                );
              },
            );
          },
        ),
      ),
    );
  }
}

方法 3:使用 Key 强制刷新特定项

如果数据变化来自外部(如网络更新),通过更新 Key 强制重建目标项。

class MyListView extends StatefulWidget {
  @override
  _MyListViewState createState() => _MyListViewState();
}

class _MyListViewState extends State<MyListView> {
  List<String> items = List.generate(20, (i) => 'Item $i');
  final Map<int, UniqueKey> _keys = {};

  @override
  void initState() {
    super.initState();
    // 初始化每个项的 UniqueKey
    for (int i = 0; i < items.length; i++) {
      _keys[i] = UniqueKey();
    }
  }

  void _updateItem(int index) {
    setState(() {
      items[index] = 'Updated Item $index';
      _keys[index] = UniqueKey(); // 更新 Key 以强制刷新
    });
  }

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) => ListTile(
        key: _keys[index], // 动态 Key
        title: Text(items[index]),
        onTap: () => _updateItem(index),
      ),
    );
  }
}

总结

  • 局部状态:优先使用 StatefulWidget 或 Provider + Selector 管理单个项的状态。

  • 唯一 Key:确保列表项有稳定且唯一的标识,避免不必要的重建。

  • 避免全局 setState:通过精细的状态控制,提升列表性能。

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

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

相关文章

如何在 Elasticsearch 中设置向量搜索 - 第二部分

作者&#xff1a;来自 Elastic Valentin Crettaz 了解如何在 Elasticsearch 中设置向量搜索并执行 k-NN 搜索。 本文是三篇系列文章中的第二篇&#xff0c;深入探讨了向量搜索&#xff08;也称为语义搜索&#xff09;的复杂性以及它在 Elasticsearch 中的实现方式。 第一部分重…

DeepSeek的出现会对百度有多大影响?

当DeepSeek与ChatGPT等大模型接管搜索入口&#xff0c;我们正见证百年一遇的信息革命。 01 传统搜索已死&#xff1f;AI助手正在重写游戏规则&#xff01; 当DeepSeek与ChatGPT等大模型接管搜索入口&#xff0c;我们正见证百年一遇的信息革命。 就像汽车淘汰马车、触屏终结按键…

PyQt学习记录01——加法计算器

目录 PyQt学习记录01——加法计算器 PyQt学习记录02——串口助手 0. 安装配置 0.1 安装相关库 首先打开你的PyCharm程序&#xff0c;然后新建一个目录用于学习&#xff0c;其次在terminal中输入 pip install pyqt5如果你不具有科学上网能力&#xff0c;请改为国内源 pip …

jenkins备份还原配置文件

下载ThinBackup插件 方式1 从插件市场直接下载 Manage Jenkins->Manage Plugins->可选插件搜索 注意&#xff1a;有时可能因为网络或者版本问题下载不了&#xff0c;好像是默认下载最新版本&#xff0c;可选择手动安装&#xff01; 方式二 手动安装插件 点击查看手…

02.11 数据库

1.思维导图 2.题目 将 epoll 服务器、客户端拿来用客户端&#xff1a;写一个界面&#xff0c;里面有注册登录服务器&#xff1a;处理注册和登录逻辑&#xff0c;注册的话将注册的账号密码写入数据库&#xff0c;登录的话查询数据库中是否存在账号&#xff0c;并验证密码是否正…

Spring Boot整合DeepSeek实现AI对话(API调用和本地部署)

本篇文章会分基于DeepSeek开放平台上的API&#xff0c;以及本地私有化部署DeepSeek R1模型两种方式来整合使用。 本地化私有部署可以参考这篇博文 全面认识了解DeepSeek利用ollama在本地部署、使用和体验deepseek-r1大模型 Spring版本选择 根据Spring官网的描述 Spring AI是一…

苹果转型独立AR眼镜:一场技术与创新的深度探索

在科技日新月异的今天,增强现实(AR)技术正逐渐从科幻电影走进我们的日常生活。作为科技界的领头羊,苹果公司的每一步动向都备受关注。近期,苹果宣布暂停原定的Mac连接式AR眼镜计划,转而全力研发一款独立的AR眼镜。这一战略调整不仅反映了苹果对AR市场的深度洞察,也预示着…

Java小白入门基础知识(一)

1.初识Java java源程序通过javac 编译生成字节码文件&#xff0c;通过java命令运行java程序 总结&#xff1a; 1&#xff09;在一个Java文件中&#xff0c;只能有一个public class 2&#xff09;public class一定要和文件名一致 3&#xff09;类里面包含方法 4&#xff09…

通过 Docker 安装和部署 KeyDB v6.3.4 的详细步骤

KeyDB 是一种高性能的开源内存数据库&#xff0c;最初是基于 Redis 项目开发的&#xff0c;但在性能、特性和功能上进行了许多增强和改进。它兼容 Redis 的大部分命令和数据结构&#xff0c;因此可以作为 Redis 的替代品使用&#xff0c;尤其是在需要更高性能和多线程支持的场景…

【JavaEE进阶】依赖注入 DI详解

目录 &#x1f334;什么是依赖注入 &#x1f384;依赖注入的三种方法 &#x1f6a9;属性注⼊(Field Injection) &#x1f6a9;Setter注入 &#x1f6a9;构造方法注入 &#x1f6a9;三种注⼊的优缺点 &#x1f333;Autowired存在的问题 &#x1f332;解决Autowired存在的…

Avnet RFSoC基于maltab得5G 毫米波 开发工具箱

使用 MATLAB 连接到 AMD Zynq™ RFSoC 评估板。使用 RF 附加卡执行 OTA 测试。使用 HDL Coder 部署算法 版本要求&#xff1a; 大于 2023b 需要以下支持包之一&#xff1a; 适用于 Xilinx 基于 Zynq 的无线电&#xff08;R2023b 及更早版本&#xff09;的通信工具箱支持包适…

neo4j-解决导入数据后出现:Database ‘xxxx‘ is unavailable. Run :sysinfo for more info.

目录 问题描述 解决方法 重新导入 问题描述 最近在linux上部署了neo4j&#xff0c;参照之前写的博客:neo4j-数据的导出和导入_neo4j数据导入导出-CSDN博客 进行了数据导出、导入操作。但是在进行导入后&#xff0c;重新登录网页版neo4j&#xff0c;发现对应的数据库状态变…

Mac(m1)本地部署deepseek-R1模型

1. 下载安装ollama 直接下载软件&#xff0c;下载完成之后&#xff0c;安装即可&#xff0c;安装完成之后&#xff0c;命令行中可出现ollama命令 2. 在ollama官网查看需要下载的模型下载命令 1. 在官网查看deepseek对应的模型 2. 选择使用电脑配置的模型 3. copy 对应模型的安…

【分布式理论9】分布式协同:分布式系统进程互斥与互斥算法

文章目录 一、互斥问题及分布式系统的特性二、分布式互斥算法1. 集中互斥算法调用流程优缺点 2. 基于许可的互斥算法&#xff08;Lamport 算法&#xff09;调用流程优缺点 3. 令牌环互斥算法调用流程优缺点 三、三种算法对比 在分布式系统中&#xff0c;多个应用服务可能会同时…

第一财经对话东土科技 | 探索工业科技新边界

当前以ChatGPT、Sora等为代表的生成式人工智能快速发展&#xff0c;越来越多面向垂直场景的行业大模型涌现出来&#xff0c;并成为推动制造业智能化改造与数字化转型、加快推进新型工业化&#xff0c;进而培育发展新质生产力的新引擎。 在垂类场景的应用落地&#xff0c;是AI发…

深入理解Java对接DeepSeek

其实&#xff0c;整个对接过程很简单&#xff0c;就四步&#xff0c;获取key&#xff0c;找到接口文档&#xff0c;接口测试&#xff0c;代码对接。 1.获取 KEY https://platform.deepseek.com/transactions 直接付款就是了&#xff08;现在官网暂停充值2025年2月7日&#xf…

线段平移 实战笔记

目录 pingyi2.py pingyi2.py import numpy as np import cv2# 画线段的函数 def draw_line(img, p1, p2, color, thickness=2):cv2.line(img, tuple(p1), tuple(p2), color, thickness)# 创建图像并初始化 def create_image():# 创建一个黑色背景图像img = np.zeros((500, 50…

WinForm 防破解、反编译设计文档

一、引言 1.1 文档目的 本设计文档旨在阐述 WinForm 应用程序防破解、反编译的设计方案&#xff0c;为开发团队提供详细的技术指导&#xff0c;确保软件的知识产权和商业利益得到有效保护。 1.2 背景 随着软件行业的发展&#xff0c;软件破解和反编译现象日益严重。WinForm…

DeepSeek应用——与word的配套使用

目录 一、效果展示 二、配置方法 三、使用方法 四、注意事项 1、永久化使用 2、宏被禁用 3、office的生成失败 记录自己学习应用DeepSeek的过程...... 这个是与WPS配套使用的过程&#xff0c;office的与这个类似&#xff1a; 一、效果展示 二、配置方法 1、在最上方的…

利用邮件合并将Excel的信息转为Word(单个测试用例转Word)

利用邮件合并将Excel的信息转为Word 效果一览效果前效果后 场景及问题解决方案 一、准备工作准备Excel数据源准备Word模板 二、邮件合并操作步骤连接Excel数据源插入合并域预览并生成合并文档 效果一览 效果前 效果后 场景及问题 在执行项目时的验收阶段&#xff0c;对于测试…