Что делает BuildContext в Flutter?
Что делает BuildContext
и какую информацию мы получаем из него?
https://docs.flutter.io/flutter/widgets/BuildContext-class.html просто неясен.
https://flutter.io/widgets-intro/#basic-widgets для 9-го экземпляра термина BuildContext
есть пример, но не ясно, как он используется. Это часть гораздо большего набора кода, который теряет меня, и поэтому мне трудно понять, что такое BuildContext
.
Может кто-нибудь объяснить это простыми/очень простыми словами?
Ответы
Ответ 1
BuildContext
, как это подразумевает название, контекст, в котором построен конкретный виджет.
Если вы когда-либо делали некоторые действия React, этот контекст похож на контекст React (но гораздо более плавный в использовании); с несколькими бонусами.
Вообще говоря, существует 2 случая использования контекста:
- Взаимодействие с вашими родителями (обычно получайте/публикуйте данные)
- После отображения на экране получите размер и положение экрана
Вторая точка немного редка. С другой стороны, первая точка используется почти везде.
Например, если вы хотите нажать новый маршрут, вы сделаете Navigator.of(context).pushNamed('myRoute')
.
Обратите внимание на контекст здесь. Он будет использоваться для получения ближайшего экземпляра виджета NavigatorState
выше в дереве. Затем вызовите метод pushNamed
в этом экземпляре.
Прохладный, но когда I хотите его использовать?
BuildContext действительно полезен, когда вы хотите передавать данные вниз, не назначая вручную все виджеты. Конфигурации, например; вы захотите получить к ним доступ повсюду. Но вы не хотите передавать его на каждый конструктор.
Вы могли бы создать глобальный или одноэлементный; но тогда, когда confs change, ваши виджеты не будут автоматически восстанавливаться.
В этом случае вы используете 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)
, автоматически перестраиваются при изменении конфигураций.
Удивительное право?
Ответ 2
Класс BuildContext
- это не что иное, как ссылка на расположение виджета в древовидной структуре всех созданных виджетов.
Каждый виджет Flutter имеет @override build()
с аргументом BuildContext
.
class CartItemWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {.....
Просто объясните, что BuildContext
это:
- BuildContext принадлежит только одному виджету.
- Объекты BuildContext передаются в функции WidgetBuilder
BuildContext принадлежит только одному виджету.
Если виджет 'A имеет дочерние виджеты, BuildContext
виджета' A станет родительским BuildContext для прямых дочерних BuildContexts
.
Читая это, становится ясно, что BuildContexts
в цепочки и составляют дерево BuildContexts
(отношения родитель-дети).
![enter image description here]()
Если мы сейчас попытаемся проиллюстрировать понятие 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)
позволяет всем static MyInheritedWidget of(BuildContext context)
виджетам получить экземпляр ближайшего MyInheritedWidget
"который заключает контекст
Наконец, переопределенный метод updateShouldNotify
используется, чтобы сообщить InheritedWidget
, нужно ли передавать уведомления всем updateShouldNotify
виджетам (которые зарегистрированы/подписаны), если к данным будет применена модификация.
для дополнительной информации
- Контекст построения
- Widget, государство, BuildContext, InheritedWidget
- Наследование виджетов