Как происходит сборка кадра (frame building) в Flutter?

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

Ответ

Flutter использует конвейер рендеринга, который обрабатывает каждый кадр в несколько этапов. Вот как это работает на практике:

Конвейер рендеринга Flutter:

// Пример виджета, демонстрирующий этапы рендеринга
class FramePipelineExample extends StatefulWidget {
  @override
  _FramePipelineExampleState createState() => _FramePipelineExampleState();
}

class _FramePipelineExampleState extends State<FramePipelineExample> 
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  double _scale = 1.0;

  @override
  void initState() {
    super.initState();
    // 1. АНИМАЦИЯ (Animation Phase)
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);

    _controller.addListener(() {
      setState(() {
        _scale = 1.0 + _controller.value * 0.5;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    // 2. ПОСТРОЕНИЕ (Build Phase)
    // Вызывается build() метод, создается дерево виджетов
    return Center(
      child: Transform.scale(
        scale: _scale,
        child: Container(
          // 3. КОМПОНОВКА (Layout Phase)
          // Вычисляются размеры и позиции
          width: 200,
          height: 200,
          // 4. ОТРИСОВКА (Paint Phase)
          // Рендеринг на GPU через Skia
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadius.circular(20),
            boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.3),
                blurRadius: 10,
                offset: Offset(0, 5),
              ),
            ],
          ),
          child: Center(
            child: Text(
              'Flutter Frame',
              style: TextStyle(
                color: Colors.white,
                fontSize: 20,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

Детальное описание этапов:

  1. Animation Phase — обновляются все анимации через AnimationController, Ticker, AnimatedBuilder
  2. Build Phase — вызываются методы build() виджетов, создается/обновляется дерево виджетов
  3. Layout PhaseRenderObject вычисляют свои размеры и позиции:
    • Родительские объекты опрашивают детей об их ограничениях
    • Дети сообщают родителям свои размеры
    • Родители позиционируют детей
  4. Paint PhaseRenderObject записывают команды рисования в Picture, который отправляется на GPU через Skia

Производительность: Flutter стремится к 60 FPS (16.6 мс на кадр) или 120 FPS (8.3 мс) на поддерживаемых устройствах. Если этап сборки занимает больше времени, возникают "джанки" (jank). Для оптимизации:

// Используйте const виджеты где возможно
const SizedBox(height: 16);
const Text('Hello');

// Разбивайте сложные build методы
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      _buildHeader(),
      _buildContent(),
      _buildFooter(),
    ],
  );
}

// Используйте ListView.builder для длинных списков
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) => ListTile(title: Text(items[index])),
);