Как работает метод `paint` в Flutter и когда он вызывается?

«Как работает метод `paint` в Flutter и когда он вызывается?» — вопрос из категории Рендеринг и производительность, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Метод paint — это ядро кастомной отрисовки в Flutter. Он объявлен в абстрактном классе CustomPainter и вызывается фреймворком, когда требуется нарисовать или перерисовать содержимое виджета CustomPaint.

Назначение параметров:

  • Canvas canvas: Инструмент для рисования примитивов (линий, фигур, текста, изображений). Он содержит трансформации (сдвиг, поворот) и клип-области.
  • Size size: Размеры доступной для рисования области, переданные от родительского виджета CustomPaint.

Типичная реализация:

class CirclePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = size.shortestSide / 2 * 0.8;

    final paint = Paint()
      ..color = Colors.blueAccent
      ..style = PaintingStyle.fill
      ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 2.0);

    canvas.drawCircle(center, radius, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // Возвращаем true только если изменились параметры,
    // влияющие на внешний вид. Это критично для производительности.
    return false;
  }
}

// Использование:
CustomPaint(
  size: const Size(100, 100),
  painter: CirclePainter(),
)

Жизненный цикл и производительность:

  1. paint вызывается при первой отрисовке и после каждого вызова setState на родительском StatefulWidget (если shouldRepaint вернул true).
  2. Внутри paint следует избегать тяжелых вычислений и создания новых объектов Paint или Path в цикле. Лучше кешировать их.
  3. Метод shouldRepaint — ключевая точка оптимизации. Он сравнивает старый и новый painter и указывает фреймворку, нужна ли перерисовка.