flutter小tip—— initState 和 build(一)

在 Flutter 开发中,有很多最佳实践和开发建议可以帮助你提高代码的质量、性能和可维护性。以下是一些常见的开发建议

1. 避免在 build 方法中执行耗时操作

  • 问题build 方法会在每次状态更新(setState)时被调用,如果里面有耗时的操作(如复杂的计算、网络请求、数据库查询等),会影响渲染性能。
  • 建议
    • 将耗时操作移到 initStateFutureBuilderProvider 等状态管理工具中。
    • 确保 build 方法只负责描述 UI。

示例(错误做法):


Widget build(BuildContext context) {final data = fetchData(); // 每次重建都会触发return Text(data);
}

改进


void initState() {super.initState();fetchData(); // 在 initState 中进行初始化
}
Widget build(BuildContext context) {return Text(_data);
}

2. 避免在 initState 中直接使用 context

  • 问题initState 中的 context 不完整,不能直接使用和 InheritedWidget 相关的内容(如 Provider)。
  • 建议
    • 如果需要使用 context,可以在 WidgetsBinding.instance.addPostFrameCallback 中处理,这样可以确保 build 方法已经被调用。

示例


void initState() {super.initState();WidgetsBinding.instance.addPostFrameCallback((_) {final provider = Provider.of<MyProvider>(context, listen: false);provider.initializeData(); // 安全使用 context});
}

3. 优化异步操作的错误处理

  • 问题:如果异步操作(如网络请求)未正确处理错误,可能会导致未捕获的异常并使应用崩溃。
  • 建议
    • 使用 try-catch 捕获错误,并提供错误处理逻辑(如显示错误提示)。
    • 为关键异步操作添加超时限制。

示例

Future<void> fetchData() async {try {final result = await fetchFromApi().timeout(Duration(seconds: 10));setState(() {_data = result;});} catch (e) {log('Error fetching data: $e');// 显示错误提示}
}

4. 使用 FutureBuilderStreamBuilder 管理异步 UI

  • 问题:手动处理异步状态(如 isLoading)容易导致复杂代码。
  • 建议
    • 使用 FutureBuilderStreamBuilder 直接绑定异步数据流和 UI,减少手动状态管理的负担。

示例

Future<String> fetchData() async {await Future.delayed(Duration(seconds: 2));return "Hello, Flutter!";
}
Widget build(BuildContext context) {return FutureBuilder<String>(future: fetchData(),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {return CircularProgressIndicator(); // 显示加载状态} else if (snapshot.hasError) {return Text('Error: ${snapshot.error}');} else {return Text(snapshot.data ?? '');}},);
}

5. 避免不必要的 setState

  • 问题:频繁调用 setState 会导致过多的页面重建,影响性能。
  • 建议
    • 尽量将状态的管理提升到外部(如 ProviderRiverpod 等状态管理工具)。
    • 使用局部更新,而不是触发整个页面的重建。

示例


void initState() {super.initState();fetchData();
}Future<void> fetchData() async {try {final newData = await fetchFromApi();// 只更新局部状态_data = newData;if (mounted) {setState(() {});}} catch (e) {log('Error fetching data: $e');}
}

6. 使用 mounted 检查组件状态

  • 问题:当异步操作在组件已经被卸载时(如页面导航后),调用 setState 会导致错误。
  • 建议
    • 在异步回调中,始终检查组件是否仍然处于挂载状态(mounted)。

示例

Future<void> fetchData() async {final result = await fetchFromApi();if (mounted) {setState(() {_data = result;});}
}

7. 拆分组件,提高可读性和性能

  • 问题:在一个组件中放置过多逻辑和 UI 代码会导致代码难以维护,并可能引发性能问题。
  • 建议
    • 将复杂的 UI 和逻辑拆分为小组件。
    • 使用 const 构造函数和 const 关键字优化性能。

示例

class MyPage extends StatelessWidget {Widget build(BuildContext context) {return Column(children: [HeaderWidget(),ContentWidget(),],);}
}class HeaderWidget extends StatelessWidget {Widget build(BuildContext context) {return Text('Header');}
}class ContentWidget extends StatelessWidget {Widget build(BuildContext context) {return Text('Content');}
}

8. 使用全局状态管理工具

  • 问题:手动传递状态和回调容易导致代码混乱。
  • 建议
    • 使用状态管理工具(如 ProviderRiverpodBlocGetX 等),将状态管理从 Widget 树中分离。

示例(使用 Provider):

class Counter with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}
Widget build(BuildContext context) {return ChangeNotifierProvider(create: (_) => Counter(),child: Consumer<Counter>(builder: (context, counter, child) {return Text('Count: ${counter.count}');},),);
}

9. 避免在 initState 中初始化大规模数据

  • 问题initState 的执行过于复杂会延迟页面加载。
  • 建议
    • initState 中启动延迟加载,并使用加载占位符(如 CircularProgressIndicator)提高用户体验。

10. 使用 const 优化性能

  • 问题:频繁重建不必要的 Widget 会影响性能。
  • 建议
    • 对静态不变的 Widget 使用 const,减少运行时的对象创建。

示例


Widget build(BuildContext context) {return const Text('This is a constant widget');
}

11. 使用 Keys 优化 ListView 和动态 UI

  • 问题:动态列表中缺少 Key 会导致不必要的渲染问题。
  • 建议
    • 使用唯一的 Key(如 ValueKeyObjectKey)标识每个子 Widget

示例

ListView.builder(itemCount: items.length,itemBuilder: (context, index) {return ListTile(key: ValueKey(items[index].id),title: Text(items[index].name),);},
);

总结

通过优化异步操作、状态管理、组件拆分和性能调优,可以对 Flutter 应用可以更高效、易维护并提供更好的用户体验

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全(3)_安全套接字层SSL

4. 安全套接字层 4.1 安全套接字层&#xff08;SSL&#xff09;和传输层安全&#xff08;TLS&#xff09; &#xff08;1&#xff09;SSL/TLS提供的安全服务 ①SSL服务器鉴别&#xff0c;允许用户证实服务器的身份。支持SSL的客户端通过验证来自服务器的证书&#xff0c;来鉴别…

【ArcGIS Pro】水文水资源、水生态与水环境

ArcGIS Pro 是一款集数据采集、处理、分析和可视化于一体的强大 GIS 工具&#xff0c;广泛应用于水文、水资源、水生态和水环境等领域。其全面的功能使得研究人员能够高效地处理各种水文和环境数据&#xff0c;从而为科学研究和决策支持提供强有力的技术保障。在水文分析方面&a…

【前端系列】Element-UI 悟道

???欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老…

中软高科身份证云解码金融(银行)解决方案介绍

多年来&#xff0c;中软高科一直深耕身份证云解码领域&#xff0c;对身份证云解码应用于金融&#xff08;银行&#xff09;&#xff0c;进行了大量且深入的研究。从长期调研来看&#xff0c;金融&#xff08;银行&#xff09;的痛点需求主要有&#xff1a; 传统身份证解码设备…

【LeetCode】每日一题 2024_12_19 找到稳定山的下标(模拟)

前言 每天和你一起刷 LeetCode 每日一题~ 最近力扣的每日一题出的比较烂&#xff0c;难度过山车&#xff0c;导致近期的更新都三天打鱼&#xff0c;两天断更了 . . . LeetCode 启动&#xff01; 题目&#xff1a;找到稳定山的下标 代码与解题思路 先读题&#xff1a;最重要…

SpringBoot开发——详解Tomcat线程池默认最大支持200并发

文章目录 1、SpringBoot 应用可以同时并发处理多少请求2、Tomcat线程池3、底层源码3.1 runWorker3.2 workQueue.offer 4、总结 1、SpringBoot 应用可以同时并发处理多少请求 Q&#xff1a;经典面试题&#xff0c;SpringBoot 应用可以同时并发处理多少请求&#xff1f; A&#…

Linux限制root 用户的远程登录(安全要求)

前言&#xff1a;现在基本用户主机都不允许使用root来操作&#xff0c;所以本文通过创建新用户&#xff0c;并限制root用户的ssh来解决这个问题 1. 创建新账户 aingo 首先&#xff0c;使用 root 账户登录系统。 sudo useradd aingo设置 aingo 账户密码&#xff1a; sudo pa…

计算机网络之王道考研读书笔记-2

第 2 章 物理层 2.1 通信基础 2.1.1 基本概念 1.数据、信号与码元 通信的目的是传输信息。数据是指传送信息的实体。信号则是数据的电气或电磁表现&#xff0c;是数据在传输过程中的存在形式。码元是数字通信中数字信号的计量单位&#xff0c;这个时长内的信号称为 k 进制码…

谁说C比C++快?

看到这个问题&#xff0c;我我得说&#xff1a;这事儿没有那么简单。 1. 先把最大的误区打破 "C永远比C快" —— 某位1990年代的程序员 这种说法就像"自行车永远比汽车省油"一样荒谬。我们来看个例子&#xff1a; // C风格 char* str (char*)malloc(100…

【Unity3D】无限循环列表(扩展版)

基础版&#xff1a;【Unity技术分享】UGUI之ScrollRect优化_ugui scrollrect 优化-CSDN博客 using UnityEngine; using UnityEngine.UI; using System.Collections.Generic;public delegate void OnBaseLoopListItemCallback(GameObject cell, int index); public class BaseLo…

Hive SQL 查询所有函数

-- 显示所有的函数 show functions; -- 对函数year进行解释 desc function year; -- 对函数year进行详细解释&#xff0c;并举例说明 desc function extended year;– 对函数year进行解释 desc function year; – 对函数year进行详细解释&#xff0c;并举例说明 desc functio…

Android13 系统签名应用编译调试说明

Android13 系统签名应用编译调试说明 文章目录 Android13 系统签名应用编译调试说明一、前言二、系统签名应用调试步骤1、新建一个应用&#xff0c;确保可以正常编译出APK2、获取系统签名文件3、Android Studio 编译安装系统权限应用&#xff08;1&#xff09;导入签名文件生成…

基于Spring Boot的医院质控上报系统

一、系统背景与意义 医院质控上报系统旨在通过信息化手段&#xff0c;实现医院质量控制的标准化、流程化和自动化管理。该系统能够帮助医院实时监控医疗质量数据&#xff0c;及时发现和处理潜在的质量问题&#xff0c;从而确保医疗服务的安全性和有效性。同时&#xff0c;系统…

将java项目部署到linux

命令解析 Dockerfile: Dockerfile 是一个文本文件&#xff0c;包含了所有必要的指令来组装&#xff08;build&#xff09;一个 Docker 镜像。 docker build: 根据 Dockerfile 或标准指令来构建一个新的镜像。 docker save: 将本地镜像保存为一个 tar 文件。 docker load: 从…

LeetCode:226.翻转二叉树

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;226.翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 …

Webpack学习笔记(2)

1.什么是loader? 上图是Webpack打包简易流程&#xff0c;webpack本身只能理解js和json这样的文件&#xff0c;loader可以让webpack解析其他类型文件&#xff0c;并且将文件转换成模块供我们使用。 test识别出那些文件被转换&#xff0c;use定义转换时使用哪个loader转换 上图…

【WebDriver】浏览器驱动下载及其配置

一、Windows电脑环境搭建-Chrome浏览器 行业内&#xff0c;Chrome (谷歌) 浏览器对于自动化程序来讲是比较稳定的. 自动化程序推荐使用 Chrome 浏览器的原因有几个&#xff1a; 开发者工具&#xff1a;Chrome 提供强大的开发者工具&#xff0c;方便调试和测试自动化脚本。 稳…

list使用

目录 list介绍 list使用 list创建 list迭代器 容量操作 元素访问 修改元素 其他操作 list介绍 ● list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代 ● list的底层是双向链表结构&#xff0c;双向链表中每个元素存…

【AIGC】如何高效使用ChatGPT挖掘AI最大潜能?26个Prompt提问秘诀帮你提升300%效率的!

还记得第一次使用ChatGPT时&#xff0c;那种既兴奋又困惑的心情吗&#xff1f;我是从一个对AI一知半解的普通用户&#xff0c;逐步成长为现在的“ChatGPT大神”。这一过程并非一蹴而就&#xff0c;而是通过不断的探索和实践&#xff0c;掌握了一系列高效使用的技巧。今天&#…

windows 使用python共享网络给另外一个网卡

# -*- coding: utf-8 -*- import subprocessdef open_share(to_shared_adapter, from_shared_adapter):"""打开以太网的网络共享:return: None"""powershell_script f"""# Register the HNetCfg library (once)# regsvr32 hnetc…