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

Что такое контекст в Dart?

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

Комментарии (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

  1. Context всегда в build методе — можете получить в build и callback'ах
  2. Не сохраняйте context долго — он может быть invalid после rebuild'а
  3. Правильный контекст для навигации — используйте контекст родительского Scaffold
  4. 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 разработки.

Что такое контекст в Dart? | PrepBro