性能优化要以数据为导向先测量再优化。本节介绍渲染、布局、内存、图片和异步五大优化方向的具体实践。一、渲染性能优化1.1 const 构造函数最高效优化手段// ❌ 每次 build() 都创建新实例Widgetbuild(BuildContextcontext){returnPadding(padding:EdgeInsets.all(16),// 没有 constchild:Text(Static Text),// 没有 const);}// ✅ const → Flutter 复用同一实例跳过重建Widgetbuild(BuildContextcontext){returnconstPadding(padding:EdgeInsets.all(16),child:Text(Static Text),);}规则只要子 Widget 的属性在编译期可知且不变都应加const。1.2 RepaintBoundary隔离重绘范围// ❌ 动画更新时整个页面的 RenderObject 都被标记为 dirtyclassChatPageextendsStatelessWidget{Widgetbuild(BuildContextcontext){returnColumn(children:[TypingIndicator(),// 每秒闪烁动画MessageList(),// 大量静态消息列表]);}}// ✅ 用 RepaintBoundary 隔离动画更新不影响 MessageListclassChatPageextendsStatelessWidget{Widgetbuild(BuildContextcontext){returnColumn(children:[RepaintBoundary(child:TypingIndicator()),// 动画在独立层RepaintBoundary(child:MessageList()),// 静态内容不会因动画重绘]);}}1.3 精细化 setState// ❌ 整个 StatefulWidget 都重建classProductPageextendsStatefulWidget{...}class_ProductPageStateextendsStateProductPage{bool isFavoritedfalse;Widgetbuild(BuildContextcontext){returnColumn(children:[ProductHeader(),// 随 isFavorited 无谓重建ProductDescription(),// 随 isFavorited 无谓重建FavoriteButton(// 只有这里需要更新isFavorited:isFavorited,onTap:()setState(()isFavorited!isFavorited),),]);}}// ✅ 方案一提取 FavoriteButton 为独立 StatefulWidget// ✅ 方案二使用 ValueNotifier ValueListenableBuilderclass_ProductPageStateextendsStateProductPage{final_isFavoritedValueNotifierbool(false);Widgetbuild(BuildContextcontext){returnColumn(children:[constProductHeader(),// const永不重建constProductDescription(),// const永不重建ValueListenableBuilderbool(valueListenable:_isFavorited,builder:(_,value,__)FavoriteButton(isFavorited:value,onTap:()_isFavorited.value!_isFavorited.value,),),]);}}二、布局性能优化2.1 避免频繁重建深层树// ❌ 将回调定义在 build() 中每次重建都创建新函数对象Widgetbuild(BuildContextcontext){returnListView.builder(itemBuilder:(context,index){returnListTile(onTap:()_handleTap(index),// 每次创建新闭包);},);}// ✅ 将静态子树提取为 const 或字段class_MyStateextendsStateMyWidget{latefinalWidget_staticHeader;overridevoidinitState(){super.initState();_staticHeaderconstExpensiveHeaderWidget();// 只创建一次}overrideWidgetbuild(BuildContextcontext){returnColumn(children:[_staticHeader,// 不会重建_buildBody(),]);}}2.2 Sliver 优化长列表// ❌ Column SingleChildScrollView所有 Widget 一次性构建SingleChildScrollView(child:Column(children:manyWidgets),)// ✅ CustomScrollView Sliver按需懒加载CustomScrollView(slivers:[// 折叠头部constSliverAppBar(expandedHeight:200,pinned:true,flexibleSpace:FlexibleSpaceBar(title:Text(标题)),),// 分组标题固定constSliverToBoxAdapter(child:CategoryHeader()),// 网格懒加载SliverGrid(delegate:SliverChildBuilderDelegate((context,index)ProductCard(product:products[index]),childCount:products.length,),gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2,),),// 列表懒加载SliverList(delegate:SliverChildBuilderDelegate((context,index)RecommendItem(item:recommendations[index]),childCount:recommendations.length,),),],)三、内存管理3.1 正确 dispose 资源class_VideoPlayerStateextendsStateVideoPlayer{lateVideoPlayerController_controller;StreamSubscription?_subscription;AnimationController?_animController;overridevoidinitState(){super.initState();_controllerVideoPlayerController.networkUrl(Uri.parse(widget.url));_animControllerAnimationController(vsync:this,duration:...);_subscriptioneventStream.listen(_handleEvent);}overridevoiddispose(){_controller.dispose();// ✅ 释放视频播放器_animController?.dispose();// ✅ 释放动画控制器_subscription?.cancel();// ✅ 取消流订阅super.dispose();}}3.2 图片内存优化// ✅ 限制图片缓存尺寸避免加载超大原图Image.network(imageUrl,cacheWidth:300,// 解码为 300 像素宽DPR 已考虑cacheHeight:300,// 避免解码 4000x4000 的原图fit:BoxFit.cover,)// ✅ 控制全局图片缓存大小voidmain(){PaintingBinding.instance.imageCache.maximumSize200;// 最多 200 张PaintingBinding.instance.imageCache.maximumSizeBytes5020;// 50MBrunApp(constMyApp());}// ✅ 不需要时手动清理图片缓存imageCache.clear();imageCache.clearLiveImages();四、图片与缓存优化dependencies:cached_network_image:^3.3.1// 带缓存、占位符和错误处理的图片加载CachedNetworkImage(imageUrl:product.imageUrl,width:200,height:200,fit:BoxFit.cover,placeholder:(context,url)constShimmerWidget(),// 骨架屏errorWidget:(context,url,error)constIcon(Icons.broken_image),memCacheWidth:400,// 内存缓存尺寸节省内存maxWidthDiskCache:800,// 磁盘缓存最大宽度)五、异步与后台计算5.1 compute简单后台任务// 在主线程finalresultawaitcompute(parseProductsJson,jsonString);// 在 Isolate 中执行独立线程ListProductparseProductsJson(StringjsonString){finallistjsonDecode(jsonString)asList;returnlist.map((e)Product.fromJson(e)).toList();}// 注意compute 的函数必须是顶层函数或 static 方法5.2 Isolate.spawn复杂后台任务FuturevoidrunHeavyTask()async{finalreceivePortReceivePort();awaitIsolate.spawn(_heavyTaskEntry,receivePort.sendPort,);finalresultawaitreceivePort.first;print(Result:$result);}// 必须是顶层函数void_heavyTaskEntry(SendPortsendPort){// 执行耗时计算finalresult_complexCalculation();sendPort.send(result);}小结优化方向关键手段效果渲染const、RepaintBoundary减少不必要重建和重绘布局Sliver懒加载、提取静态树降低初始化和重建开销内存dispose 资源、控制图片缓存尺寸防止内存泄漏图片CachedNetworkImage、cacheWidth减少内存和解码开销异步compute、Isolate.spawn耗时操作移离主线程 下一章八、工程化与模块化