Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Context в Flutter/Dart — контекст построения виджета
Context (BuildContext) — это объект, который содержит информацию о позиции виджета в дереве виджетов (widget tree). Он предоставляет доступ к различным сервисам Flutter и является ключевым компонентом при разработке Flutter приложений.
Основная идея
Context служит для:
- Навигации — переход между экранами (Navigator.push)
- Доступ к Theme — получение текущей темы приложения
- Управление State — доступ к родительским виджетам (Provider, GetX)
- Показ диалогов — showDialog, showModalBottomSheet
- Media Query — получение размеров экрана, ориентации
- Управление Focus — фокус на текстовых полях
Получение Context
// Context доступен в методе build
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// context доступен здесь
return Text('Hello');
}
}
// Или через GlobalKey для StatefulWidget
class MyStatefulWidget extends StatefulWidget {
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
final GlobalKey<_MyStatefulWidgetState> _key = GlobalKey();
@override
Widget build(BuildContext context) {
// context доступен здесь
return Text('Hello');
}
}
Практические примеры
Навигация между экранами:
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
// Навигация с использованием context
Navigator.push(
context,
MaterialPageRoute(builder: (_) => DetailScreen()),
);
},
child: Text('Go to Details'),
),
),
);
}
}
Доступ к Theme:
class StyledText extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Получаем текущую тему через context
final theme = Theme.of(context);
return Text(
'Styled Text',
style: theme.textTheme.headlineMedium,
);
}
}
Показ диалога:
class MyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
// Показываем диалог через context
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Confirm'),
content: Text('Do you want to continue?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: Text('OK'),
),
],
),
);
},
child: Text('Show Dialog'),
);
}
}
Media Query через context:
class ResponsiveWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Получаем размер экрана через context
final screenSize = MediaQuery.of(context).size;
final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
return Column(
children: [
Text('Width: ${screenSize.width}'),
Text('Height: ${screenSize.height}'),
Text('Orientation: ${isPortrait ? "Portrait" : "Landscape"}'),
],
);
}
}
Доступ к State через Context (Provider pattern):
mixin Locator {
static T read<T>(BuildContext context) {
return context.read<T>();
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Получаем State через context
final userProvider = context.read<UserProvider>();
final user = userProvider.user;
return Text('Hello ${user.name}');
}
}
FocusScope для управления фокусом:
class LoginForm extends StatefulWidget {
@override
State<LoginForm> createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final emailFocus = FocusNode();
final passwordFocus = FocusNode();
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
focusNode: emailFocus,
onSubmitted: (_) {
// Переводим фокус на пароль через context
FocusScope.of(context).requestFocus(passwordFocus);
},
),
TextField(
focusNode: passwordFocus,
),
],
);
}
@override
void dispose() {
emailFocus.dispose();
passwordFocus.dispose();
super.dispose();
}
}
Иерархия Context
Context отражает иерархию виджетов:
MaterialApp (context1)
├── Scaffold (context2)
│ └── AppBar (context3)
└── Center (context4)
└── Column (context5)
└── Text (context6)
Каждый виджет имеет свой context, и вы можете получать информацию об уровне выше.
Важные правила при работе с Context
- Context всегда в build методе — можете получить в build и callback'ах
- Не сохраняйте context долго — он может быть invalid после rebuild'а
- Правильный контекст для навигации — используйте контекст родительского Scaffold
- Context в async методах — проверьте mounted перед использованием context
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Future<void> _loadData() async {
await Future.delayed(Duration(seconds: 2));
// Проверяем, что виджет еще в дереве
if (!mounted) return;
// Теперь можно использовать context безопасно
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Data loaded')),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ElevatedButton(
onPressed: _loadData,
child: Text('Load'),
),
);
}
}
Типичные ошибки
// ❌ ОШИБКА: Context может быть invalid
BuildContext? savedContext;
void onPressed(BuildContext context) {
savedContext = context;
}
void later() {
Navigator.push(savedContext!, MaterialPageRoute(...)); // Может упасть!
}
// ✅ ПРАВИЛЬНО: Используйте context сразу
void onPressed(BuildContext context) {
Navigator.push(context, MaterialPageRoute(...));
}
Итого
Context — это критически важный объект в Flutter, который:
- Предоставляет доступ ко всем сервисам Flutter
- Отражает позицию виджета в дереве
- Используется для навигации, управления состоянием, стилизации
- Должен использоваться с осторожностью (может быть invalid)
Понимание Context — это фундамент для успешной Flutter разработки.