Офер за 1 день в команду BetterMe (Frontend Hiring, JavaScript/React/Redux)
×Закрыть

Flutter: что такое Context

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Всем привет, меня зовут Даниил! И я Flutter разработчик в компании AppVesto.

В этой статье мы разберемся что из себя представляет context и как его правильно использовать.

Что такое Widget

Чтобы убедиться, что мы на одной волне, давайте начнем с понятия Widget. Наверняка, вы слышали такую фразу: «Все во Flutter — это виджеты.» Однако, это не совсем правильно.

Корректнее будет сказать, что виджеты — это все, что отображается на экране. Общий макет страницы, положение и размер кнопки, цвет и размер текста — все это создано с использованием виджетов.

Что такое дерево виджетов

Виджеты во Flutter имеют иерархическую структуру или, иными словами, виджеты организованы в виде дерева.

  • Виджет, который содержит в себе другие виджеты называется родительским виджетом или parent Widget.
  • Виджеты, которые хранятся в родительском виджете, называются дочерними или children Widgets.

Рассмотрим небольшой пример стандартного кода, который автоматически генерируется при создании нового проекта.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }

Виджет Scaffold является родительским виджетом для Center, а Center, в свою очередь, является родительским для Column. Соответственно, Column — это дочерний виджет Center.

Как создать виджет

Для создания любого виджета используется метод build, который принимает в качестве аргумента BuildContext.

BuildContext — это описание позиции виджета в дереве виджетов. Именно этот класс описывает отношение parent-children и позволяет реализовать такие функции как showDialog, Theme.of и некоторые другие функции, которые позволяют использовать контекст родительского виджета, например его размеры и местоположение.

BuildContext используется, чтобы избежать прямого манипулирования родительским виджетом и получить необходимую информацию, которая содержится в родительском контексте.

Что вам необходимо знать о context

  • Context — это ссылка на расположение виджета в древовидной структуре виджетов.
  • Контекст может принадлежать только одному виджету.
  • Если у виджета есть дочерние виджеты, то контекст родительского виджета становится родительским контекстом для контекстов прямых дочерних элементов.
  • Виджет виден только в его собственном контексте или в контексте его родительского контекста.

Таким образом, становится понятно, что зная дочерний контекст, можно легко найти родительский виджет. И наоборот, с помощью родительского контекста можно найти дочерний виджет.

Метод ‘of()’

Как мы уже знаем, виджеты во Flutter имеют структуру дерева и могут общаться с другими виджетами, находящимися как ниже, так и выше по дереву виджетов.

«Общение» виджетов между собой обеспечивается методом Of().

Давайте рассмотрим небольшой пример:

@override
Widget build(context) {
  return Text('Subscribe to the AppVesto Instagram!',
    style: TextStyle(color: Theme.of(context).primaryColor),
  );
}

Метод of() ищет в дереве виджетов родительский виджет, который имеет тип Theme, и использует его свойство primaryColor для текущего виджета.

Это возможно благодаря тому, что Flutter знает положение объекта Theme в дереве по отношению к текущему buildContext.

Метод of() может быть полезен для решения многих задач, например для получения размера экрана с помощью MediaQuery.of(context) или навигации с помощью Navigator.of(context). Для создания некоторых виджетов, таких как snackBar нужно использовать ближайший контекст Scaffold, чтобы Flutter мог его корректно отрисовать на экране.

При выполнении следующего кода вы получите ошибку: «Scaffold.of() called with a context that does not contain a Scaffold».

Пример (Не работает):

Widget build(BuildContext context) {
 return Scaffold(
   appBar: AppBar(
 	title: Text(widget.title),
   ),
   body: Center(
 	child: RaisedButton(
   	child: Text('Show Snack Bar'),
   	onPressed: () {
     	Scaffold.of(context).showSnackBar(
       	SnackBar(
         	backgroundColor: Colors.blue,
             content: Text('I am SNACKBAR!!!'),
           ),
         );
   	},
 	),
   ),
 );
}

Данный код не работает потому что виджет Scaffold еще не создан, а контекст который был передан в метод build указывает на родителя который не содержит Scaffold.

Итак, как же предоставить дочернему виджету snackBar доступ к родительскому виджету Scaffold?

Для того чтобы исправить возникшую проблему, обернем кнопку виджетом Builder и все заработает:

Widget build(BuildContext context) {
 return Scaffold(
   appBar: AppBar(
 	title: Text(widget.title),
   ),
   body: Center(
 	child: Builder(
   	builder: (BuildContext context) {
     	return RaisedButton(
       	child: Text('Show Snack Bar'),
           onPressed: () {
         	Scaffold.of(context).showSnackBar(
           	SnackBar(
             	backgroundColor: Colors.blue,
             	content: Text('I am SNACKBAR!!!'),
               ),
             );
           },
         );
   	},
 	),
   ),
 );
}

Builder позволяет получить и использовать контекст виджета в котором находится сам Builder. В примере выше это виджет Scaffold.

Если у вас остались какие-то вопросы, задавайте их в комментариях и я с радостью на них отвечу.

👍НравитсяПонравилось0
В избранноеВ избранном3
Подписаться на автора
LinkedIn

Похожие статьи

Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Могли бы вы показать производительность списка с загрузкой картинок? Чтоб листать список и картинки асинхронно подгружались. Интересно, как у флаттера обстоят дела с этим.

Flutter — о*уенный. Просто решил написать.

прям не поленился залогиниться и плюсануть )

Flutter — безодня досконалості

Спасибо за статью. Такой вопрос не по статье, после перехода Flutter Engine под Ios на Metal, при старте приложение, анимации и переходы по виджетам значительно подвисают, вы как-то решаете данную проблему ?

Надо ждать фикс от разработчиков. Даже новый Google Pay с этой проблемой зарелизился

Лол. Это всё, что нужно знать о флатере.

У новых технологий всегда есть детские болячки. Рано еще судить

о боже, щось лагає на 4% девайсах ринку. і то не зрозуміло що.

Подписаться на комментарии