2026/2/21 5:49:18
网站建设
项目流程
要做网站照片怎么处理,用狐狸做logo的网站,中国室内设计大赛官网,类似站酷的网站建站网罗开发#xff08;小红书、快手、视频号同名#xff09;大家好#xff0c;我是 展菲#xff0c;目前在上市企业从事人工智能项目研发管理工作#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术#xff0c;包括iOS、前端、Harmony OS、Java、Python等方…网罗开发小红书、快手、视频号同名大家好我是展菲目前在上市企业从事人工智能项目研发管理工作平时热衷于分享各种编程领域的软硬技能知识以及前沿技术包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。图书作者《ESP32-C3 物联网工程开发实战》图书作者《SwiftUI 入门进阶与实战》超级个体COC上海社区主理人特约讲师大学讲师谷歌亚马逊分享嘉宾科技博主华为HDE/HDG我的博客内容涵盖广泛主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告同时也会提供产品优缺点分析、横向对比并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。展菲您的前沿技术领航员 大家好我是展菲 全网搜索“展菲”即可纵览我在各大平台的知识足迹。 公众号“Swift社区”每周定时推送干货满满的技术长文从新兴框架的剖析到运维实战的复盘助您技术进阶之路畅通无阻。 微信端添加好友“fzhanfei”与我直接交流不管是项目瓶颈的求助还是行业趋势的探讨随时畅所欲言。 最新动态2025 年 3 月 17 日快来加入技术社区一起挖掘技术的无限潜能携手迈向数字化新征程文章目录前言rebuild 本身不是问题失控才是Flutter 的 build 到底是怎么被触发的最常见的问题setState 用得太“随手”拆 Widget是最立竿见影的优化手段const Widget 不是装饰是性能保障InheritedWidget 和 Provider 为什么容易“连坐”用 Selector 精准控制 rebuildRiverpod 中的 rebuild 控制思路用 DevTools 找 rebuild 热点而不是靠感觉总结前言如果你做 Flutter 开发一段时间大概率遇到过这种情况只是点了一下按钮页面却像“抖”了一下列表滚动开始掉帧动画也没以前顺了。更让人困惑的是——你明明没改 UI 结构只是改了一个状态。这篇文章就专门聊一个在 Flutter 项目里几乎绕不开的问题页面为什么会频繁 rebuild以及我们该如何一步步把它控制住。不会只停留在概念解释我会结合真实开发场景把 build 的触发链路拆清楚并配上可以直接跑的 Demo。rebuild 本身不是问题失控才是很多人一听到 rebuild 就条件反射式紧张其实这是个常见误解。在 Flutter 里build 并不等于重绘build 也不等于重新创建 RenderObjectbuild 更像是“重新生成一份 UI 描述”Flutter 的设计前提就是build 要轻量、可频繁调用。真正影响性能的从来不是“有没有 rebuild”而是rebuild 的范围是不是太大不该 rebuild 的地方有没有被牵连build 里有没有做了重活后面的所有优化其实都围绕一个核心目标把 rebuild 限制在最小、最合理的范围内。Flutter 的 build 到底是怎么被触发的很多教程都会简单地说一句setState 会触发 build这句话没错但太笼统了。从底层角度看真实流程更像这样状态发生变化 ↓ Element 被标记为 dirty ↓ Flutter 在下一帧统一调度 build ↓ 重新生成 Widget 子树有两个关键点经常被忽略setState 并不会立刻重建 UIFlutter 会在一帧内合并多次状态变更这也是 Flutter 在高频交互下依然能保持流畅的原因之一。最常见的问题setState 用得太“随手”下面这个例子基本是很多人项目里的真实写照。classCounterPageextendsStatefulWidget{overrideStateCounterPagecreateState()_CounterPageState();}class_CounterPageStateextendsStateCounterPage{int count0;overrideWidgetbuild(BuildContextcontext){print(CounterPage build);returnScaffold(appBar:AppBar(title:Text(Counter)),body:Column(children:[Text(Count:$count),ElevatedButton(onPressed:(){setState((){count;});},child:Text(Add),),HeavyWidget(),],),);}}classHeavyWidgetextendsStatelessWidget{overrideWidgetbuild(BuildContextcontext){print(HeavyWidget build);returnContainer(height:200,color:Colors.blue,);}}你点一次按钮控制台会输出CounterPage build HeavyWidget build问题就来了HeavyWidget 和 count 有任何关系吗没有但它还是被 rebuild 了。原因也很简单setState 作用在父节点整个子树都会被标记为需要重建。拆 Widget是最立竿见影的优化手段很多性能问题并不是 Flutter 本身的问题而是页面结构的问题。最常见的模式是整个页面是一个 StatefulWidget所有状态都集中在最外层任意一个字段变化整个页面重建其实只要稍微调整结构就能解决一大半问题。classCounterPageextendsStatelessWidget{overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text(Counter)),body:Column(children:[CounterView(),HeavyWidget(),],),);}}classCounterViewextendsStatefulWidget{overrideStateCounterViewcreateState()_CounterViewState();}class_CounterViewStateextendsStateCounterView{int count0;overrideWidgetbuild(BuildContextcontext){print(CounterView build);returnColumn(children:[Text(Count:$count),ElevatedButton(onPressed:(){setState((){count;});},child:Text(Add),),],);}}现在再点按钮你会发现只有 CounterView 在 rebuildHeavyWidget 完全不会受影响在真实业务里这种拆分非常常见比如筛选条件和列表分离表单项和提交按钮分离动画区域和业务状态分离const Widget 不是装饰是性能保障很多人知道要写 const但并不知道它的真正意义。Text(Hello);和constText(Hello);在频繁 rebuild 的场景下差别非常明显。const Widget 的核心价值在于Flutter 可以直接复用已有实例避免不必要的对象创建和比较在拆好 Widget 之后再配合 const效果会非常明显。classStaticHeaderextendsStatelessWidget{constStaticHeader({super.key});overrideWidgetbuild(BuildContextcontext){returnText(Static Header,style:TextStyle(fontSize:24),);}}哪怕父节点 rebuild这类 Widget 的成本几乎可以忽略。InheritedWidget 和 Provider 为什么容易“连坐”当你在 build 里写下finalusercontext.watchUserModel();实际上发生的是当前 Widget 订阅了 UserModelUserModel 任何字段变化所有依赖它的 Widget 都会 rebuild如果 UserModel 很“胖”问题就会被无限放大。用 Selector 精准控制 rebuild假设有这样一个模型classUserModelextendsChangeNotifier{Stringname;int age;UserModel(this.name,this.age);voidupdateAge(int newAge){agenewAge;notifyListeners();}}不推荐的写法是Text(context.watchUserModel().name);更合理的方式是SelectorUserModel,String(selector:(_,model)model.name,builder:(_,name,__){returnText(name);},);这样一来age 变化不会 rebuildname 变化才会触发更新这在列表页、用户信息页里非常重要。Riverpod 中的 rebuild 控制思路如果你使用 Riverpod本质思路是一样的。finalcountProviderStateProviderint((ref)0);尽量避免在大 Widget 中直接 watchfinalcountref.watch(countProvider);可以通过拆 Widget或者使用 select让 rebuild 更精确。用 DevTools 找 rebuild 热点而不是靠感觉Flutter DevTools 提供了非常实用的工具打开 Performance勾选 rebuild / repaint 高亮页面中频繁闪烁的区域通常就是优化突破口。同时一个非常原始但有效的方法是overrideWidgetbuild(BuildContextcontext){debugPrint(build:${runtimeType});return...}在复杂页面中这个手段非常好用。总结如果你不想每次都重新分析这里有一套通用原则rebuild 本身不是问题范围失控才是StatefulWidget 尽量下沉能 const 的 Widget 一定要 const拆 Widget 是最优先的优化方式状态监听一定要精确用工具定位而不是凭感觉猜这些经验基本来自所有中大型 Flutter 项目的踩坑总结。