StatelessWidget gets rebuilt even though parameters stay the same; notifyListeners() with ChangeNotifier
I've got two StatelessWidgets, one is a child of another. There is also a progress update function which updates the state in the external TransferState
. Once updateProgress
function is being called the TransferIndicator
widget gets rebuilt immediately. On the other hand, its parent (TransfersListTile
) build method isn't called.
It works as expected, however I can't really work out what's the mechanism that's being used here. How Flutter decides to rebuild the: _TransferIndicator
given that the parameter is a string hash
that's not being changed, but only used as a lookup ID to reach the map
in TransferState
and load the status
and progress
.
Documentation: https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html says:
"The build method of a stateless widget is typically only called in three situations: the first time the widget is inserted in the tree, when the widget's parent changes its configuration, and when an InheritedWidget it depends on changes."
If: notifyListeners();
function is removed, the widget doesn't get rebuilt.
It seem to be closely related to: ChangeNotifier
, but couldn't find the exact info how it works.
In doc here: https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple#changenotifier there is an example involving ChangeNotifier
, however doesn't the receiving widget need to be wrapped around: Consumer
(https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple#consumer)? In my case there is no Consumer
wrapping.
class TransfersListTile extends StatelessWidget {
TransfersListTile(this.transfer, {Key? key}) : super(key: key);
final Transfer transfer;
@override
Widget build(BuildContext context) {
return ListTile(
leading: _TransferIndicator(transfer.hash),
title: Text(transfer.name!),
);
}
}
class _TransferIndicator extends StatelessWidget {
const _TransferIndicator(this.hash, {Key? key}) : super(key: key);
final String? hash;
@override
Widget build(BuildContext context) {
final status = context.select((TransferState s) => s.map[hash]?.status) ?? TransferStatus.pending;
final progress = context.select((TransferState s) => s.map[hash].progress.percentage);
return CircularProgressIndicator(
value: status == TransferStatus.completed ? 100 : (progress / 100),
);
}
}
function:
class TransferState with ChangeNotifier {
updateProgress(String hash, TransferProgress progress) {
map[hash]?.progress = progress;
notifyListeners();
}
}
and provider part:
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => TransferState(),
],
child: MyApp(),
)
);
Comments
Post a Comment