Well the issue is kinda simple, but it needs to be done on a specific way. First I have a Class extending "ChangeNotifier" this class will perform some async tasks, so while it is doing so there's a variable that indicates if the class is currently bussy or not, so far it works flawlessly.
Using Riverpod as state managment I instanciate said class and provide it along my widget tree, but there's one Widget that needs to display a dialog and inside this dialog it can execute async tasks from the Class that I've been passing around. It all works except for the fact that I would like to display a CircularProgressIndicator inside this dialog, and it doesn't seems to be reacting propperly to the state changes.
Here's a sample code to recreate the scenario:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
final dataProvider = ChangeNotifierProvider<Data>((_) => Data());
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'huh?',
theme: ThemeData(primarySwatch: Colors.blue),
home: FirstPage(),
);
}
}
class FirstPage extends HookWidget {
@override
Widget build(BuildContext context) {
final data = useProvider(dataProvider);
print('DATA STATE [source: FirstPage, data: ${data.loading}]');
return Scaffold(
body: Center(
child: Container(
width: 200,
height: 50,
child: ElevatedButton(
child: Text('show dialog'),
onPressed: () => showDialog(
context: context,
builder: (_) => Alert(data: data),
),
),
),
),
);
}
}
class Alert extends StatelessWidget {
const Alert({required this.data});
final Data data;
Widget build(BuildContext context) {
print('DATA STATE [source: Alert, data: ${data.loading}]');
return AlertDialog(
content: Container(
width: 500,
height: 500,
padding: EdgeInsets.symmetric(horizontal: 100, vertical: 200),
child: ElevatedButton(
child: data.loading ? CircularProgressIndicator(color: Colors.white) : Text('click here'),
onPressed: () async => await data.randomTask(),
),
),
);
}
}
class Data extends ChangeNotifier {
Data({
this.loading = false,
});
bool loading;
Future<void> randomTask() async {
print('Actually waiting 3 seconds..');
_update(loading: true);
await Future.delayed(Duration(seconds: 3));
print('Waiting done.');
_update(loading: false);
}
void _update({bool? loading}) {
this.loading = loading ?? this.loading;
notifyListeners();
}
}
Notice the prints I've placed, because of them if you run the app you'll see outputs on the console like:
DATA STATE [source: FirstPage, data: false]
DATA STATE [source: Alert, data: false]
Actually waiting 3 seconds..
DATA STATE [source: FirstPage, data: true]
Waiting done.
DATA STATE [source: FirstPage, data: false]
Which means that the state is actually changing, and everything is working fine, except for the dialog that seems to be static.
I already tried adding a "loading" bool as part of the "Alert" widget, and letting it manage its own state, and it works, but the code is not as clean as I would like to, because the Class "Data" is supposed to manage this kind of stuff.
Is there anything that can be done?
Thankyou in advance!