В Flutter контекст относится к расположению виджета в дереве виджетов. Он предоставляет информацию об окружающей среде и сервисах, которые могут понадобиться виджету.
Например, контекст может содержать такую информацию, как тема приложения, локаль, размер экрана и многое другое. Обращаясь к контексту, виджет может принимать решения о том, как отображать себя, исходя из контекста.
Во Flutter контекст передается по дереву виджетов от родителя к ребенку, что позволяет дочерним виджетам получать доступ к контексту их родителей и предков. Это позволяет виджетам использовать информацию из более высоких частей дерева без необходимости передавать ее в качестве аргумента каждому виджету на этом пути.
В Flutter существуют различные способы доступа к контексту, но наиболее распространенным является использование аргумента BuildContext в методе сборки виджета. Вы также можете получить доступ к контексту из обработчиков событий, таких как onPressed, используя аргумент context в обратном вызове.
Используя контекст, можно создавать многократно используемые виджеты, которые могут адаптироваться к среде и сервисам, в которых они используются, что упрощает создание сложных и гибких пользовательских интерфейсов.В более простом смысле контекст во Flutter можно представить как рюкзак, который вы носите с собой повсюду. Рюкзак содержит то, что вам нужно знать о том, где вы находитесь и что делаете.
Например, в нем может быть информация о месте, в котором вы находитесь, о том, который сейчас час, и о том, какой ваш любимый цвет.
Когда вы собираете игрушку с помощью Flutter, вы хотите, чтобы ваша игрушка знала о некоторых вещах, которые находятся в вашем рюкзаке. Например, вы можете захотеть, чтобы ваша игрушка знала, какого цвета ваш рюкзак, чтобы ее можно было покрасить в этот цвет. Контекст — это способ передачи информации от рюкзака к игрушке.
Подобно тому, как вы можете передать свой рюкзак друзьям, контекст передается от одного виджета Flutter к другому. Таким образом, ваша игрушка может получить доступ ко всей необходимой ей информации без необходимости спрашивать ее у вас каждый раз, когда ей нужно что-то узнать.
If (understood) return;
Все еще не можете понять? Продолжайте читать.
Представьте, что вы строите игрушечный домик. Вы хотите, чтобы ваш игрушечный домик знал тему комнаты, в которой он находится, чтобы его можно было украсить соответствующим образом. Например, тема может быть ”пляжный домик”, поэтому игрушечный домик будет украшен ракушками, песком и другими предметами, связанными с пляжем.
Чтобы предоставить информацию о теме игрушечному домику, можно передавать ее в качестве аргумента каждый раз при создании нового виджета. Однако это быстро становится громоздким и сложным в обслуживании, особенно по мере того, как ваш игрушечный домик становится все сложнее и имеет больше частей.
С контекстами во Flutter вы можете определить информацию о теме один раз, в корне дерева виджетов, и сделать ее автоматически доступной для всех виджетов далее по дереву. Виджеты могут получить доступ к контексту без необходимости знать что-либо о виджетах, расположенных выше по дереву.
Таким образом, контексты облегчают управление потоком информации в вашем приложении Flutter и позволяют создавать многократно используемые и гибкие виджеты, которые могут адаптироваться к своему окружению и необходимым им сервисам.
class ThemeChanger extends StatefulWidget {
final Widget child;
final String theme;
ThemeChanger({@required this.child, @required this.theme});
@override
_ThemeChangerState createState() => _ThemeChangerState();
}
class _ThemeChangerState extends State<ThemeChanger> {
String _currentTheme;
@override
void initState() {
_currentTheme = widget.theme;
super.initState();
}
void changeTheme(String newTheme) {
setState(() {
_currentTheme = newTheme;
});
}
@override
Widget build(BuildContext context) {
return Theme(
data: _currentTheme == "green" ? ThemeData(primarySwatch: Colors.green) : ThemeData(primarySwatch: Colors.blue),
child: widget.child,
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Context Example"),
actions: [
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
final themeChanger =
context.ancestorWidgetOfExactType(ThemeChanger);
themeChanger.changeTheme(themeChanger._currentTheme == "green" ? "blue" : "green");
},
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("The theme can be changed dynamically"),
],
),
),
);
}
}
void main() {
runApp(
ThemeChanger(
theme: "green",
child: MaterialApp(
home: MyHomePage(),
),
),
);
}
В этой версии виджет MyHomePage имеет действие в панели приложений, которое позволяет пользователю изменить тему. Когда пользователь нажимает на значок обновления, тема меняется с зеленой на синюю или наоборот.
Виджет MyHomePage использует метод ancestorWidgetOfExactType для доступа к виджету ThemeChanger, который является родительским виджетом, хранящим текущую тему. Затем он вызывает метод changeTheme виджета ThemeChanger, чтобы динамически изменить тему.
Это демонстрирует, как контексты могут быть использованы для упрощения динамического изменения темы, без необходимости передавать информацию о теме в качестве аргументов вниз по дереву виджетов.
Что такое ancestorWidgetOfExactType?
ancestorWidgetOfExactType - это метод класса BuildContext во Flutter, который возвращает ближайший виджет-предок указанного типа. Он принимает единственный аргумент, который является типом виджета-предка, который вы хотите найти.Этот метод полезен, когда вы хотите получить доступ к виджету, который находится выше в дереве виджетов, но не хотите передавать его в качестве аргумента всем промежуточным виджетам. Вместо этого вы можете использовать ancestorWidgetOfExactType для поиска ближайшего предка определенного типа и затем использовать этот виджет для доступа к данным или вызова методов на нем.
В предыдущем примере мы используем это для поиска виджета ThemeChanger.