← Назад к вопросам

Что такое StatelessWidget?

1.3 Junior🔥 281 комментариев
#Flutter виджеты

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

StatelessWidget в Flutter

StatelessWidget — это базовый тип виджета в Flutter, который представляет неизменяемую часть пользовательского интерфейса. Это один из двух основных типов widgets в Flutter, наряду со StatefulWidget.

Определение и концепция

StatelessWidget — это виджет, который не имеет состояния. Его состояние не может изменяться во время жизненного цикла. Если нужно что-то изменить, нужно создать новый экземпляр виджета.

// StatelessWidget — неизменяемый, как константа
const StatelessWidget = FrozenUI();

Структура StatelessWidget

class MyButton extends StatelessWidget {
  final String label;
  final VoidCallback onPressed;
  
  const MyButton({
    required this.label,
    required this.onPressed,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      child: Text(label),
    );
  }
}

Ключевые моменты:

  • Наследуемся от StatelessWidget
  • Параметры хранятся в final полях
  • Конструктор помечен как const (когда возможно)
  • Переопределяем только метод build()

Жизненный цикл StatelessWidget

1. Создание экземпляра (constructor)
2. Вызов build() метода один раз
3. Отрисовка на экране
4. Если parent обновился — пересчет build() с новыми параметрами
5. Удаление с экрана

ВНИМАНИЕ: Метод build() вызывается как при создании, так и при изменении параметров!

Практические примеры

Пример 1: Простой текстовый компонент

class AppTitle extends StatelessWidget {
  final String title;
  final String? subtitle;
  
  const AppTitle({
    required this.title,
    this.subtitle,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          title,
          style: Theme.of(context).textTheme.headlineMedium,
        ),
        if (subtitle != null)
          Text(
            subtitle!,
            style: Theme.of(context).textTheme.bodyMedium,
          ),
      ],
    );
  }
}

// Использование:
AppTitle(
  title: 'Welcome',
  subtitle: 'Hello Flutter',
)

Пример 2: Кастомная кнопка

class CustomButton extends StatelessWidget {
  final String label;
  final VoidCallback onPressed;
  final ButtonStyle? style;
  
  const CustomButton({
    required this.label,
    required this.onPressed,
    this.style,
  });

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      style: style,
      child: Text(label),
    );
  }
}

// Использование
CustomButton(
  label: 'Submit',
  onPressed: () => handleSubmit(),
)

Пример 3: Карточка с информацией

class UserCard extends StatelessWidget {
  final String name;
  final String email;
  final String avatarUrl;
  final VoidCallback onTap;
  
  const UserCard({
    required this.name,
    required this.email,
    required this.avatarUrl,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        leading: CircleAvatar(
          backgroundImage: NetworkImage(avatarUrl),
        ),
        title: Text(name),
        subtitle: Text(email),
        onTap: onTap,
      ),
    );
  }
}

StatelessWidget vs StatefulWidget

СвойствоStatelessWidgetStatefulWidget
ИзменяемостьНеизменяемыйИзменяемый
СостояниеНетЕсть (State класс)
Методы жизниТолько build()initState, dispose и др.
ОбновлениеНовый экземплярsetState()
ПроизводительностьБыстрееМедленнее (больше контекста)
ИспользованиеPresentational UIИнтерактивные элементы

Когда использовать StatelessWidget

Используй StatelessWidget для:

// 1. Простые компоненты UI
const ProgressBar();
const AppLogo();
const CustomButton();

// 2. Когда данные передаются через параметры
const UserProfile(user: user);

// 3. Когда состояние управляется родителем
const SearchField(
  value: query,
  onChanged: handleChange,
)

// 4. Неизменяемые данные
const ThemeProvider(
  theme: appTheme,
  child: MyApp(),
)

НЕ используй StatelessWidget когда:

// ❌ Неправильно: StatelessWidget не может управлять изменяемым состоянием
class Counter extends StatelessWidget {
  int count = 0; // ОШИБКА!
  
  void increment() {
    count++; // Ничего не изменится на UI!
  }
}

// ✅ Правильно: используй StatefulWidget
class Counter extends StatefulWidget {
  @override
  State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int count = 0;
  
  void increment() {
    setState(() => count++);
  }
}

Оптимизация производительности

1. Используй const конструкторы

// ✅ Хорошо: const виджеты не пересчитываются
class Header extends StatelessWidget {
  final String title;
  
  const Header({required this.title}); // const!
  
  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

// Использование
const Header(title: 'Home'); // const!

2. Выноси сложные виджеты в отдельные StatelessWidget'ы

// ❌ Плохо: все в одном build()
build() {
  return Column(
    children: [
      // 100 строк кода для заголовка
      // 100 строк кода для контента
      // 100 строк кода для футера
    ],
  );
}

// ✅ Хорошо: разделить на компоненты
build() {
  return Column(
    children: [
      const Header(),
      const Content(),
      const Footer(),
    ],
  );
}

3. Мемоизация с помощью const

// Хотя эти код выглядит одинаково — они разные!
const button1 = MyButton(label: 'OK');
const button2 = MyButton(label: 'OK');

// button1 и button2 могут быть переиспользованы (одна инстанция)
builder1() => const MyButton(label: 'OK');
builder2() => const MyButton(label: 'OK');

// Если нет const, каждый раз создается новая инстанция
builder1() => MyButton(label: 'OK'); // NEW
builder2() => MyButton(label: 'OK'); // NEW

Лучшие практики

  1. Всегда делай конструктор const

    const MyWidget({required this.title});
    
  2. Используй final для всех параметров

    final String title;
    final int count;
    
  3. Используй required для обязательных параметров

    const MyWidget({required this.title});
    
  4. Разделяй на мелкие StatelessWidget'ы

    • Легче тестировать
    • Легче переиспользовать
    • Лучше производительность
  5. Передавай callbacks вместо логики

    // ✅ Правильно
    onPressed: () => handleClick();
    
    // ❌ Неправильно: логика в виджете
    onPressed: () => setState(() => count++);
    

StatelessWidget — это основной строительный блок Flutter приложений. Большинство компонентов UI должны быть именно StatelessWidget'ами. Используй StatefulWidget только когда действительно нужно управлять изменяемым состоянием.

Что такое StatelessWidget? | PrepBro