You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Scaffold::appBar状态变更时触发CustomPainter::paint()调用

解决AppBar状态变化时CustomPainter不必要重绘的问题

问题根源

当AppBar内按钮状态变化触发父组件PageTestState的build方法重新执行时,_body()会每次新建PageTestPainter实例。即使shouldRepaint返回false,Flutter检测到CustomPainter实例更换后,依然会触发paint()方法调用。

可行解决方案

方案一:缓存CustomPainter实例

在State类中初始化并复用同一个CustomPainter实例,避免每次build都创建新对象:

class PageTestState extends State<PageTest> {
  late PageTestPaint _painter;

  @override
  void initState() {
    super.initState();
    // 初始化一次,后续复用
    _painter = PageTestPaint();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: const Text('Page Test'),
        titleTextStyle: const TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
        centerTitle: true,
        actions: [
          IconButton(
            icon: const Icon(Icons.radio_button_checked, color: Colors.redAccent),
            onPressed: () {},
          ),
        ],
      ),
      body: _body(),
    );
  }

  Widget _body() {
    return Center(
      child: CustomPaint(
        painter: _painter, // 使用缓存的实例
      ),
    );
  }
}

方案二:封装为独立StatelessWidget

将包含CustomPaint的部分抽成单独的无状态组件,父组件重建时,只要子组件无参数变化,就不会重新构建:

// 新增独立组件
class CustomPaintContainer extends StatelessWidget {
  const CustomPaintContainer({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: CustomPaint(
        painter: PageTestPaint(),
      ),
    );
  }
}

// 修改PageTestState的build方法
class PageTestState extends State<PageTest> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: const Text('Page Test'),
        titleTextStyle: const TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
        centerTitle: true,
        actions: [
          IconButton(
            icon: const Icon(Icons.radio_button_checked, color: Colors.redAccent),
            onPressed: () {},
          ),
        ],
      ),
      body: const CustomPaintContainer(),
    );
  }
}

原理说明

两种方案的核心都是保证CustomPainter实例不被频繁重建。因为shouldRepaint返回false时,只有当CustomPainter实例本身变化时,Flutter才会触发paint()方法,只要实例稳定,AppBar的状态变化就不会影响到CustomPainter的重绘。

内容的提问来源于stack exchange,提问作者wingchun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:02:22