The minimal reproducible code below aims to have a loading icon when a button is pressed(to simulate loading when asynchronous computation happen).
For some reason, the Consumer Provider doesn't rebuild the widget when during the callback.
My view:
class HomeView extends StatefulWidget {
const HomeView();
@override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ChangeNotifierProvider(
create: (_) => HomeViewModel(99),
child: Consumer<HomeViewModel>(
builder: (_, myModel, __) => Center(
child: ButtonsAtBottom(
addEventAction: () => myModel.increment(context),
busy: myModel.busy
),
),
),
),
);
}
}
My model where I simulate to do business logic:
class HomeViewModel extends LoadableModel {
late int integer;
HomeViewModel(this.integer);
void increment(BuildContext context) {
super.setBusy(true);
Future.delayed(Duration(seconds: 3), () => print(integer++));
super.setBusy(false);
//Passed in context just to try to simulate my real app
//print(context);
}
}
class LoadableModel extends ChangeNotifier {
bool _busy = false;
bool get busy => _busy;
void setBusy(bool value) {
_busy = value;
notifyListeners();
}
}
PROBLEM: When the callback executes, and setBusy()
methods within it are executed, they should notify the listeners and update the busy
field passed in it. Subsequently, either a text or loader should be displayed.
BUT, busy
field is never updated and remains as false
.
class ButtonsAtBottom extends StatelessWidget {
final bool busy;
final void Function() addEventAction;
const ButtonsAtBottom({required this.busy, required this.addEventAction});
@override
Widget build(BuildContext context) {
print("busy value: $busy");
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () => Navigator.pop(context),
icon: Icon(Icons.clear_rounded),
),
ElevatedButton.icon(
onPressed: addEventAction,
icon: Icon(Icons.save_alt_rounded),
label: busy
? CircularProgressIndicator.adaptive(
backgroundColor: Colors.white,
)
: Text("Save")),
],
);
}
}
did you try to await
the future
?