Что делает BuildContext во Флаттере?

Я пытаюсь выучить Флаттер и довольно рано бьюсь о стену. Что делает BuildContext и какую информацию мы получаем из него?

https://docs.flutter.io/flutter/widgets/BuildContext-class.html просто неясен.

https://flutter.io/widgets-intro/ 9-го экземпляра термина "BuildContext", есть пример, но неясно, как он используется. Это часть гораздо большего набора кода, который теряет меня, и поэтому мне трудно понять, что такое BuildContext.

Может кто-нибудь объяснить это простыми / очень простыми словами? Благодарю.

1 ответ

Решение

BuildContext это, как следует из названия, контекст, в котором построен конкретный виджет.

Если вы когда-либо делали какой-то React раньше, этот контекст похож на контекст React (но гораздо удобнее в использовании); с несколькими бонусами.

Вообще говоря, есть 2 варианта использования для контекста:

  • Взаимодействовать с родителями (чаще всего получать / публиковать данные)
  • После визуализации на экране получите размер и положение экрана

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

Например, когда вы хотите протолкнуть новый маршрут, вы будете делать Navigator.of(context).pushNamed('myRoute'),

Обратите внимание на контекст здесь. Он будет использован для получения ближайшего экземпляра NavigatorState виджет выше в дереве. Затем вызовите метод pushNamed в этом случае.


Круто, но когда я хочу использовать это?

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

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

В этом случае вы используете InheritedWidget, С его помощью вы могли бы написать следующее:

class Configuration extends InheritedWidget {
  final String myConf;

  const Configuration({this.myConf, Widget child}): super(child: child);

  @override
  bool updateShouldNotify(Configuration oldWidget) {
    return myConf != oldWidget.myConf;
  }
}

И затем используйте это так:

void main() {
  runApp(
    new Configuration(
      myConf: "Hello world",
      child: new MaterialApp(
        // usual stuff here
      ),
    ),
  );
}

Благодаря этому теперь везде внутри вашего приложения вы можете получить доступ к этим конфигам, используя BuildContext, При выполнении

final configuration = context.inheritFromWidgetOfExactType(Configuration);

И даже круче то, что все виджеты, которые называют inheritFromWidgetOfExactType(Configuration) будет автоматически перестроен при изменении конфигурации.

Круто, верно?

BuildContext Класс - это не что иное, как ссылка на расположение виджета в древовидной структуре всех созданных виджетов.

Каждый виджет Flutter имеет @override build() метод с аргументом BuildContext,

class CartItemWidget extends StatelessWidget {

  @override
  Widget build(BuildContext context) {.....

Просто объясните, что BuildContext является:

  1. BuildContext принадлежит только одному виджету.
  2. Объекты BuildContext передаются в функции WidgetBuilder

BuildContext принадлежит только одному виджету.

Если виджет "А" имеет дочерние виджеты, BuildContext виджета 'A' станет родительским BuildContext для прямых потомков BuildContexts,

Читая это, ясно, что BuildContexts прикованы и составляют дерево BuildContexts (отношения родителей и детей)

Если мы сейчас попытаемся проиллюстрировать понятие BuildContext на предыдущей диаграмме, мы получим (все еще в очень упрощенном виде), где каждый цвет представляет BuildContext (кроме MyApp, который отличается):

На следующей диаграмме показана (упрощенная версия) последовательность действий / вызовов, связанных с созданием виджета с отслеживанием состояния.

Состояние виджета не зависит от параметров, и все же он перестраивался при каждом изменении параметров. В таком случае нужно использовать InheritedWidget

InheritedWidget это особый вид виджета, который определяет контекст в корне поддерева. Он может эффективно доставить этот контекст каждому виджету в этом поддереве. Шаблон доступа выглядел бы знакомым для разработчиков Flutter:

class MyInheritedWidget extends InheritedWidget {

MyInheritedWidget({
      Key key,
      @required Widget child,
      this.data,
   }): super(key: key, child: child);

   final data;

   static MyInheritedWidget of(BuildContext context) {
      return context.inheritFromWidgetOfExactType(MyInheritedWidget);
   }

   @override
   bool updateShouldNotify(MyInheritedWidget oldWidget) => data != oldWidget.data;
}

static MyInheritedWidget of(BuildContext context) метод, позволяет всем дочерним виджетам получить экземпляр ближайшего MyInheritedWidget ", Который охватывает контекст

Наконец, updateShouldNotify переопределенный метод используется, чтобы сказать InheritedWidget нужно ли передавать уведомления всем дочерним виджетам (которые зарегистрированы / подписаны), если к данным будут применены изменения

для дополнительной информации

  1. Создайте контекст
  2. Widget, государство,BuildContext,InheritedWidget
  3. Наследование виджетов

Дерево виджетов Flutter состоит из 2 типов виджетов.

Виджет 1-класса (родительский виджет / класс расширяется виджетом без состояния или с сохранением состояния)

2- построить виджет (дочерний виджет / виджет, возвращаемый build()

Оба виджета имеют собственный контекст.


Контекст

Что на самом деле означает контекст????

context - это параметр (переменная), который содержит значение (объект),value = location(позиция), который создается этим виджетом.

Заметка:- Это значение (местоположение) / аргумент для этого параметра задаетсяFrameworkавтоматически, когда виджет построен.; так что не думайте о том, как этот параметр получает значение

У каждого виджета есть место сборки???

ДА, каждый виджет имеет место сборки, без этого фреймворка местоположения не может создать дерево элементов этого дерева виджетов (имейте в виду, что это также полезно для разработчиков)

Есть 02 типа контекста

1 - Контекст виджета класса (родительский виджет)

2 - построить контекст виджета (дочерний виджет)

  • Контекст виджета класса - этот контекст нам не виден, он используется только самим фреймворком для создания дерева элементов.

  • контекст построения виджета - этот контекст видим для нас, его использование фреймворком, а также мы используем его в некоторых целях (например: - для доступа к предыдущему виджету)

--------------------------------------------------------------------------------------

контекст виджета сборки / контекст BuildContext

контекст виджета сборки - это тип контекста, который вы передали для метода build() (как показано ниже)

@override
Widget build(BuildContext context) {            //BuildContext
  return Text(
    'Example',
    style: Theme.of(context).textTheme.title,
  );
}

Все знают, что переменная или параметр имеет свой тип.(например, int, double, String..etc)

Таким образом, этот параметр контекста также имеет тип BuildContext.

(Это специальное имя "BuildContext" хорошо представляет значение этого контекста, поскольку этот контекст принадлежит методу сборки, поэтому он получает имя как "BuildContext")


Где находится этот виджет

Чтобы ответить на этот вопрос, см. Приведенный ниже код, он покажет вам место сборки этого виджета (и это место является хранилищем в объекте контекста (параметр).

См. Ниже код флаттера, там вы можете увидеть комментарий //here is the location of this child widget is build..Этот комментарий обозначает место сборки этого дочернего виджета.

Пример кода - 1

@override
Widget build(BuildContext context) {
  //here is the location of this child widget is build.
  return Text(
    'Example',
    style: Theme.of(context).textTheme.title,
  );
}

Пример кода -2

@override
  Widget build(BuildContext context) {
    // here build location of that widget                     //here
    return Scaffold(
      appBar: AppBar(title: Text('Demo')),
      body: Builder(
        // here build location of that widget                 //here
        builder: (BuildContext context) {
          return FlatButton(
            child: Text('BUTTON'),
            onPressed: () {
              Scaffold.of(context).showSnackBar(SnackBar(
                content: Text('Hello.')
              ));
            }
          );
        }
      )
    );
  }

В этом посте я рассказывал вам о значении контекста. Но здесь я не показывал варианты использования контекста BuildContext, но некоторые варианты использования показаны в ответе @Remi Rousselet.

Надеюсь, что это поможет вам

Другие вопросы по тегам