Как происходит обновление виджетов
Обновление виджетов
Flutter может вызывать метод build() в нескольких ситуациях:
- После вызова метода
iniState() - После вызова метода
didUpdateWidget() - После вызова метода
setState() - После того как зависимости
Stateобъекта были изменены (InheritedWidget) - После
deactivate(), а затем повторной вставки объектаStateв дерево.
Метод build() может быть вызван довольно часто и при этом не должен иметь никаких побочных эффектов, кроме создания виджета.
Переданный аргумент build(BuildContext context) содержит информацию о том месте в дереве, в котором создается этот виджет. Например, контекст предоставляет набор унаследованных виджетов для этого места в дереве. Аргумент BuildContext всегда совпадает со свойством контекста этого объекта State и остается неизменным в течение всего времени существования этого объекта.
Практический пример
Рассмотрим случай когда StatefulWidget находится внутри другого StatefulWidget и происходит вызов метода didUpdateWidget()
Файл 3_stateful_didUpdateWidget.dart
class TrackCardExample3 extends StatefulWidget {
const TrackCardExample3({super.key});
@override
State createState() => _TrackCardExample3State();
}
class _TrackCardExample3State extends State {
int counter = 0;
void _incCount() => setState(() {
counter++;
});
@override
Widget build(BuildContext context) {
debugPrint("🔵 TrackCardExample3 build (widget hash: ${identityHashCode(widget)})");
return Card(
color: Colors.white,
child: ListTile(
leading: Image.asset("assets/images/pro.webp"),
title: const TitleWidget(text: "Stateless"),
subtitle: const SubtitleWidget(text: "Flutter vibes"),
trailing: LikeButton(
text: "Like $counter",
incCount: _incCount,
),
),
);
}
}
class TitleWidget extends StatelessWidget {
final String text;
const TitleWidget({super.key, this.text = ""});
@override
Widget build(BuildContext context) {
debugPrint("🔵 TitleWidget build (widget hash: ${identityHashCode(this)})");
return Text(
text,
style: TextStyle(
fontWeight: FontWeight.bold,
),
);
}
}
class SubtitleWidget extends StatelessWidget {
final String text;
const SubtitleWidget({super.key, this.text = ""});
@override
Widget build(BuildContext context) {
debugPrint("🔵 SubtitleWidget build (widget hash: ${identityHashCode(this)})");
return Text(text.toUpperCase());
}
}
class LikeButton extends StatefulWidget {
final String text;
final Function incCount;
const LikeButton({
super.key,
this.text = "",
required this.incCount,
});
@override
State createState() => _LikeButtonState();
}
class _LikeButtonState extends State {
bool isFavorite = false;
@override
void didUpdateWidget(covariant LikeButton oldWidget) {
super.didUpdateWidget(oldWidget);
debugPrint("LikeButton identityHashCode oldWidget = "
"${identityHashCode(oldWidget)}, "
"newWidget = ${identityHashCode(widget)}");
}
@override
Widget build(BuildContext context) {
debugPrint("🔵 LikeButton build isFavorite: $isFavorite, widget hash: ${identityHashCode(widget)}");
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: IconButton(
onPressed: () {
isFavorite = !isFavorite; // Не обязательно вызывать ещё один setState
widget.incCount(); // Вызываем функцию-колбэк из виджета TrackCard
},
icon: isFavorite
? const Icon(Icons.favorite, color: Colors.red)
: const Icon(Icons.favorite_border),
),
),
Text(widget.text),
],
);
}
}
Как происходит обновление виджетов
Слайды. Как происходит обновление виджетов