Ответ
Это три фундаментальных типа виджетов во Flutter с разным предназначением:
-
StatelessWidget
- Неизменяемый (immutable). Все его поля должны быть
final. - Не хранит собственное изменяемое состояние. Он описывает часть UI, которая зависит только от своих входных параметров (
props) и контекста. -
Создается заново при каждом изменении родительского виджета.
class MyTitle extends StatelessWidget { final String text; // Параметр — final поле const MyTitle(this.text, {super.key}); @override Widget build(BuildContext context) { return Text(text, style: Theme.of(context).textTheme.headlineMedium); } }
- Неизменяемый (immutable). Все его поля должны быть
-
StatefulWidget
- Состоит из двух классов: сам неизменяемый виджет (
StatefulWidget) и изменяемый объект состояния (State). - Хранит изменяемое состояние (данные, которые могут меняться в течение жизни виджета).
-
Перестраивает UI при вызове
setState()в его объектеState.class Counter extends StatefulWidget { const Counter({super.key}); @override State<Counter> createState() => _CounterState(); }
class _CounterState extends State
{ int _count = 0; // Изменяемое состояние void _increment() { setState(() { // Триггер перерисовки _count++; }); }
@override Widget build(BuildContext context) { return ElevatedButton( onPressed: _increment, child: Text('Нажато $_count раз'), ); } }
- Состоит из двух классов: сам неизменяемый виджет (
-
InheritedWidget
- Специальный виджет для эффективного распространения данных вниз по дереву.
- Позволяет любому потомку в поддереве получить доступ к данным без их явной передачи через конструкторы каждого промежуточного виджета (решает "проблему проваливания пропсов").
- Ключевой механизм для таких сущностей, как
Theme,MediaQuery, а также для state-менеджмента в пакетах вродеProvider.// Потомок получает данные через статический метод .of(context) final themeData = Theme.of(context); final screenSize = MediaQuery.of(context).size;
Итог: Stateless и Stateful — строительные блоки UI. InheritedWidget — это инфраструктурный виджет для передачи данных и управления зависимостями.
Ответ 18+ 🔞
Э, сабака сука, слушай сюда, я тебе сейчас про три кита Flutter'а расскажу, чтобы ты не ходил потом как манда с ушами. Это же ёперный театр, как люди путаются!
Первый тип — StatelessWidget. Это как твой старый дед, который уже нихуя не меняется. Он родился с такими параметрами — такими и помрёт. Все поля у него final, то есть конченые. Он просто рисует интерфейс на основе того, что ему скормили сверху, и всё. Родитель поменял данные — этого деда выкинули нахуй и создали нового, с новыми данными. Никакой своей памяти, никакого состояния. Просто рисует и не парится.
class MyTitle extends StatelessWidget {
final String text; // Вот видишь? final. Принял и зафиксировал.
const MyTitle(this.text, {super.key});
@override
Widget build(BuildContext context) {
return Text(text, style: Theme.of(context).textTheme.headlineMedium);
}
}
Второй — StatefulWidget. А вот это уже хитрая жопа. Он состоит из двух половинок, как полупидор какой-то. Первая половинка — сам виджет — тоже вроде как неизменяемая обёртка. Но внутри у него живёт вторая половинка — объект State (состояние). И вот эта штука — она помнит всё! Нажал кнопку — счётчик увеличился, вызвал setState() — и виджет перерисовался, но объект состояния-то остался жить! Он хранит эти изменяемые данные. Без него интерактивность — пизда рулю.
class Counter extends StatefulWidget {
const Counter({super.key});
@override
State<Counter> createState() => _CounterState(); // Родил состояние
}
class _CounterState extends State<Counter> {
int _count = 0; // А вот оно, изменяемое состояние! Может расти.
void _increment() {
setState(() { // Магический пинок для перерисовки
_count++;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _increment,
child: Text('Нажато $_count раз'), // Смотри, данные из состояния!
);
}
}
Третий — InheritedWidget. Это вообще отдельная песня, ядрёна вошь. Представь, ты на самом верху дерева виджетов, и тебе нужно передать, например, тему вниз, глубоко-глубоко. Ты что, будешь прокидывать её через конструкторы двадцати промежуточных виджетов, которые сами по себе в ней не нужны? Это же пиздопроебибна! Вот для этого и есть InheritedWidget. Он вешает данные на дерево, а любой его потомок может до них дотянуться ручкой, через context, без всей этой ебалы с передачей. Theme.of(context) или MediaQuery.of(context) — это всё он, красавец, работает.
// Сидишь где-то в глубине, и тебе вдруг понадобилась тема.
// Не надо ничего прокидывать! Просто:
final themeData = Theme.of(context); // Взял и вытащил. Волшебство, блядь.
final screenSize = MediaQuery.of(context).size;
Итог, ёпта: Stateless и Stateful — это кирпичи, из которых стены лепишь. А InheritedWidget — это скрытая проводка и система вентиляции, которую ты раскидываешь по всему дому, чтобы потом в любой комнате мог включить свет, не таская с собой генератор. Понял теперь, чувак?