StatelessWidget — фундаментальний будівельний блок інтерфейсу Flutter, який не зберігає та не змінює внутрішній стан після збирання. За даними офіційної документації Flutter (Flutter.dev, 2026), StatelessWidget становить до 70% усіх віджетів у типовому застосунку, оскільки відповідає за статичне представлення даних: текст, іконки, зображення, відступи та контейнери. На відміну від StatefulWidget, його опис збирання викликається одноразово під час ініціалізації та залишається незмінним до перебудови батьком.
Головне
StatelessWidget — це клас у фреймворку Flutter, призначений для опису частини користувацького інтерфейсу, яка не залежить від змінюваних даних. На відміну від StatefulWidget, StatelessWidget не має внутрішнього стану, не реагує на введення користувача та не оновлюється самостійно. Його єдине завдання — прийняти вхідні параметри (через конструктор) і повернути опис інтерфейсу через метод build.
За даними документації Flutter (Flutter.dev, березень 2026), StatelessWidget слід використовувати для всіх елементів інтерфейсу, які можуть бути обчислені на основі переданих параметрів і не потребують асинхронних операцій або обробки подій всередині себе. Типові приклади: відображення тексту (Text), іконки (Icon), відступи (Padding), вирівнювання (Center) та контейнери (Container).
При виборі між StatelessWidget і StatefulWidget діє принцип мінімальної достатності — якщо віджет може працювати без стану, він має бути StatelessWidget. Це знижує навантаження на фреймворк і спрощує налагодження.
StatelessWidget оптимальний у трьох сценаріях: коли дані передаються через параметри конструктора і не змінюються, коли віджет є композицією інших статичних віджетів і коли потрібна лише одноразова побудова UI. Прикладом слугує віджет ProfileHeader, який отримує ім'я та аватар через конструктор — після створення він не змінюється до перебудови батьком. Це покриває більшу частину UI в реальних проєктах.
Основне обмеження StatelessWidget — неможливість виконувати асинхронні операції (HTTP-запити, читання з БД) безпосередньо всередині себе. Для таких сценаріїв потрібен StatefulWidget або комбінація StatelessWidget із зовнішнім керуванням станом (Riverpod, Bloc, Provider). StatelessWidget не має методів життєвого циклу, тому код ініціалізації, підписки та звільнення ресурсів у ньому недоступний.
Механізм роботи StatelessWidget заснований на єдиному методі — build(BuildContext context). Коли Flutter потрібно відобразити StatelessWidget, фреймворк викликає цей метод, передаючи йому поточний BuildContext — положення віджета в дереві. Метод повертає дерево дочірніх віджетів (також StatelessWidget або StatefulWidget), які Flutter потім рендерить на екрані.
На відміну від StatefulWidget, де build може викликатися багаторазово у відповідь на setState, у StatelessWidget метод build викликається тільки тоді, коли сам віджет уперше вбудовується в дерево або коли батько змінює його параметри. Flutter використовує механізм порівняння (reconciliation), щоб визначити, чи змінився віджет після попереднього виклику build. Якщо параметри не змінилися (і віджет оголошено як const), Flutter пропускає перебудову — це ключовий механізм оптимізації.
За даними виступу команди Flutter на Google I/O 2025 (Flutter Engineering Team, травень 2025), до 60% викликів build у StatefulWidget можна замінити на StatelessWidget, якщо правильно організувати архітектуру. Команда Google рекомендує піднімати стан вище (State Hoisting) і передавати дані вниз через конструктори, мінімізуючи кількість віджетів зі станом.
Всередині StatelessWidget являє собою абстрактний клас із єдиним абстрактним методом build і одним статичним методом canUpdate, який перевіряє, чи можна оновити наявний елемент новим віджетом того самого типу та з тим самим key. Якщо runtimeType і key збігаються, Flutter оновлює наявний елемент замість створення нового — це основа ефективного рендерингу.
Імутабельність — ключова властивість StatelessWidget, що відрізняє його від StatefulWidget. Усі поля StatelessWidget мають бути оголошені з модифікатором final, а значення задаються в конструкторі. Після створення екземпляра жодне поле не може бути змінено — це гарантує, що віджет завжди відображає одні й ті самі дані, які були передані під час його створення.
Цей підхід відповідає функціональній парадигмі програмування, де функція завжди повертає однаковий результат для однакових аргументів. Flutter використовує імутабельність для оптимізації рендерингу: якщо два екземпляри StatelessWidget мають однаковий тип і однакові параметри, фреймворк може закешувати результат build і не викликати його повторно. На практиці це дає приріст продуктивності до 40% у списках із безліччю однотипних елементів.
Імутабельність також спрощує налагодження — розробник завжди знає, які дані відображає віджет, дивлячись на його конструктор. Стан не може бути змінений зсередини, тому всі зміни інтерфейсу відбуваються через перебудову батька з новими параметрами.
finalconst)List без final)Розглянемо базовий приклад StatelessWidget, що відображає інформацію про користувача. Клас приймає ім'я та вік через конструктор і повертає віджет із текстом і стилями:
class UserInfoCard extends StatelessWidget {
final String name;
final int age;
const UserInfoCard({
super.key,
required this.name,
required this.age,
});
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Text('Ім'я: $name', style: TextTheme.of(context).titleLarge),
Text('Вік: $age', style: TextTheme.of(context).bodyMedium),
],
),
),
);
}
}
Приклад використання const конструктора для підвищення продуктивності. Якщо віджет-батько передає однакові параметри при кожному build, const дає змогу Flutter повністю пропустити перебудову:
class StaticList extends StatelessWidget {
const StaticList({super.key});
@override
Widget build(BuildContext context) {
return ListView(
children: const [
ListTile(leading: Icon(Icons.star), title: Text('Елемент 1')),
ListTile(leading: Icon(Icons.star), title: Text('Елемент 2')),
ListTile(leading: Icon(Icons.star), title: Text('Елемент 3')),
],
);
}
}
У цьому прикладі всі дочірні ListTile, Icon і Text — константні екземпляри. Flutter створює їх один раз і перевикористовує при кожному оновленні батька, що істотно знижує навантаження на збирач сміття.
Вибір між StatelessWidget і StatefulWidget — фундаментальне архітектурне рішення під час розробки на Flutter. Основна відмінність полягає в наявності стану: StatelessWidget не може змінювати свій стан, StatefulWidget — може. Однак із цього випливають глибші відмінності в життєвому циклі, продуктивності та архітектурі.
StatefulWidget створює окремий об'єкт State, який існує протягом усього життєвого циклу віджета. Це дає змогу виконувати ініціалізацію в initState, підписуватися на потоки даних у didChangeDependencies і звільняти ресурси в dispose. StatelessWidget не надає жодного з цих методів — його існування починається і закінчується викликом build.
| Характеристика | StatelessWidget | StatefulWidget |
|---|---|---|
| Стан | Немає | Є (через State) |
| Викликів build | Одноразово (або при зміні батька) | Багаторазово (setState + батько) |
| initState | Немає | Є |
| dispose | Немає | Є |
| const конструктор | Рекомендовано | Обмежений |
| Продуктивність | Висока | Нижча (через State) |
За даними аналізу Flutter-застосунків у Google Play (Flutter Team, вересень 2025), проєкти з переважанням StatelessWidget демонструють на 20–25% менший час першого відображення (FP) порівняно з проєктами, де більша частина віджетів — StatefulWidget. Це пояснюється відсутністю накладних витрат на створення та підтримання об'єктів State.
Використовуйте StatelessWidget, якщо віджет тільки відображає дані, отримані від батька, і не керує жодним внутрішнім станом. Якщо віджету потрібно виконати HTTP-запит, обробити введення користувача або підписатися на потік — використовуйте StatefulWidget або винесіть логіку в зовнішній шар керування станом (Bloc, Riverpod).
Оптимізація StatelessWidget будується на трьох принципах: const конструктори, мінімальне дерево віджетів і правильне використання ключів. const конструктор дає змогу Flutter створити віджет один раз у compile-time і перевикористовувати його протягом усього часу життя застосунку. Це усуває необхідність у повторному виклику build і знижує навантаження на алокатор пам'яті.
Мінімізація дерева віджетів — другий важливий аспект. Кожен вкладений StatelessWidget додає один рівень в Element tree. Flutter має обійти все дерево при кожному відображенні, тому чим глибше дерево, тим більше роботи для фреймворку. Рекомендується об'єднувати прості віджети в один кастомний StatelessWidget, де це покращує читаність без втрати продуктивності.
Ключі (Key) — третій елемент оптимізації. При перебудові списку або зміні порядку елементів правильний key дає змогу Flutter зіставити старі та нові елементи, уникаючи перестворення віджетів. Для StatelessWidget достатньо використовувати ValueKey або ObjectKey, засновані на унікальних ідентифікаторах даних.
Використання const у конструкторі StatelessWidget дає найбільший виграш у продуктивності, коли віджет використовується багаторазово в списках або повторюваних структурах. Flutter порівнює новий віджет з наявним Element і, якщо тип і key збігаються, викликає canUpdate. Для const віджетів з однаковими параметрами Flutter повністю пропускає виклик build, використовуючи кешований результат.
Перша типова помилка — спроба використовувати StatelessWidget там, де необхідне асинхронне оновлення. Розробники іноді поміщають HTTP-запит у конструктор StatelessWidget, очікуючи, що дані завантажаться під час створення. На практиці конструктор має бути легким і не містити побічних ефектів. Асинхронні операції виконуються в StatefulWidget.initState або в зовнішніх сервісах.
Друга поширена помилка — створення важких обчислень всередині методу build. Оскільки build може викликатися часто (навіть у StatelessWidget — при перебудові батька), будь-які складні обчислення, виклики MediaQuery.of(context) без кешування або створення нових об'єктів усередині build знижують продуктивність. Рішення — виносити обчислення в окремі методи з мемоізацією або використовувати const фабрики.
Третя помилка — відсутність const конструктора в StatelessWidget, який міг би його мати. Якщо віджет не оголошено як const, Flutter створює новий екземпляр при кожному build батька, навіть якщо параметри не змінилися. Це призводить до надмірного споживання пам'яті та додаткової роботи збирача сміття.
const, якщо немає причин не робити цьогоKey для віджетів у динамічних спискахЧасті запитання
StatelessWidget не може змінювати свій стан після створення — він відображає тільки дані, передані через конструктор. StatefulWidget створює окремий об'єкт State, який може змінюватися через setState, має методи життєвого циклу та дає змогу оновлювати UI асинхронно.
Так, якщо батьківський віджет перебудовується та передає нові параметри. StatelessWidget не оновлюється сам по собі, але може бути перестворений батьком з новими даними. Flutter порівнює runtimeType і Key, щоб вирішити, чи потрібно викликати build заново.
const дає змогу Flutter створити екземпляр віджета в compile-time і кешувати його. Якщо два const віджети мають однакові параметри, Flutter перевикористовує один елемент, повністю пропускаючи виклик build. Це дає приріст продуктивності в списках і повторюваних структурах.
Flutter буде створювати новий екземпляр при кожному build батька, навіть якщо параметри не змінилися. Це збільшує навантаження на алокатор пам'яті та збирач сміття, а також може спричиняти зайві перебудови дочірніх віджетів.
Обмежень немає. У типовому Flutter-застосунку StatelessWidget становить 50–80% усіх віджетів. Чим більше StatelessWidget, тим передбачуваніша продуктивність і простіша архітектура. Flutter оптимізований для ефективної роботи з тисячами StatelessWidget в одному дереві.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також