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

Flutter中CustomPainter的shouldRepaint()方法是如何工作的?

一文搞懂Flutter CustomPainter的shouldRepaint逻辑

先搞懂这个方法的作用边界

不用抠官方那些绕口的术语,一句话说清:shouldRepaint 是仅当CustomPaint组件的painter实例被替换时,才会触发的优化判断开关,它不是全局的重绘总开关,也管不到其他场景的重绘逻辑。
这就直接解答你最懵的问题:为啥返回false的时候视图也会重绘?因为父组件setState、系统触发界面刷新这些场景下的重绘,和这个方法没有关系,该重绘还是会重绘。这个方法只是给你多了一个「减少不必要paint调用」的优化机会而已。

什么时候该返回false?

只要你的CustomPainter画的内容是完全固定、没有任何可变参数的,直接返回false就行。
举个最简单的例子:你要画一个永远不会变的红色圆形,不管什么时候新建这个Painter实例,画出来的内容都一模一样:

import 'package:flutter/material.dart';

class StaticRedCirclePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.red;
    // 画一个占满组件的红色圆形
    canvas.drawCircle(size.center(Offset.zero), size.width / 2, paint);
  }

  @override
  bool shouldRepaint(covariant StaticRedCirclePainter oldDelegate) {
    // 新旧实例画的内容完全一致,不需要重绘
    return false;
  }
}

这种场景下返回false,就算父组件频繁setState导致CustomPaint重新build,Flutter对比新旧Painter的时候发现shouldRepaint返回false,就会跳过paint方法的执行,能省不少性能。

什么时候该返回true?

当你的CustomPainter有可变的入参,参数变了绘制内容就会变的时候,你就对比新旧实例的可变参数,只要参数变了就返回true,没变就返回false。
举个例子:你要做一个进度环,进度值是外部传进来的,进度变了环的颜色、弧度都要变:

import 'package:flutter/material.dart';
import 'dart:math';

class ProgressRingPainter extends CustomPainter {
  // 可变入参:进度值0~1
  final double progress;

  const ProgressRingPainter(this.progress);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 8
      // 颜色从红到绿随进度渐变
      ..color = Color.lerp(Colors.red, Colors.green, progress)!;
    // 画对应进度的圆弧
    canvas.drawArc(
      Rect.fromLTWH(0, 0, size.width, size.height),
      -pi / 2,
      2 * pi * progress,
      false,
      paint,
    );
  }

  @override
  bool shouldRepaint(covariant ProgressRingPainter oldDelegate) {
    // 只有进度值变了的时候才需要重绘
    return oldDelegate.progress != progress;
  }
}

用的时候如果进度从0.3更新到0.5,新的Painter实例和旧的对比进度值不一样,返回true,Flutter就会重新执行paint方法绘制新的进度环;如果进度没变化,就返回false跳过绘制,性能拉满。

常见困惑点统一解答

  • 不是说Flutter自己会管重绘吗为啥还要写这个?:Flutter的重绘优化是针对组件树的,而CustomPainter的paint逻辑是自定义的,Flutter不知道你两次传的Painter画的内容是不是一样,所以需要你主动告诉它,多一层优化。
  • paint不就是定义绘制规则的吗?:没错,但如果规则完全没变,没必要重复执行paint方法,这个方法就是用来判断规则有没有变的。
  • 为啥很多示例直接返回false?:大部分Demo都是静态绘制的场景,没有可变参数,所以直接返回false就行。
  • 为啥要强制重写这个方法?:就是怕开发者随便写导致不必要的性能损耗,强制让你根据自己的绘制逻辑做判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:24:04