Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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
| Свойство | StatelessWidget | StatefulWidget |
|---|---|---|
| Изменяемость | Неизменяемый | Изменяемый |
| Состояние | Нет | Есть (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
Лучшие практики
-
Всегда делай конструктор
constconst MyWidget({required this.title}); -
Используй
finalдля всех параметровfinal String title; final int count; -
Используй
requiredдля обязательных параметровconst MyWidget({required this.title}); -
Разделяй на мелкие StatelessWidget'ы
- Легче тестировать
- Легче переиспользовать
- Лучше производительность
-
Передавай callbacks вместо логики
// ✅ Правильно onPressed: () => handleClick(); // ❌ Неправильно: логика в виджете onPressed: () => setState(() => count++);
StatelessWidget — это основной строительный блок Flutter приложений. Большинство компонентов UI должны быть именно StatelessWidget'ами. Используй StatefulWidget только когда действительно нужно управлять изменяемым состоянием.