I have an application with Flutter and Riverpod, so i created a provider for the AuthController like this
final authControllerProvider = StateNotifierProvider<AuthController, bool>((ref) {
final authApi = ref.watch(authApiProvider);
final userApi = ref.watch(userApiProvider);
final localStorage = ref.watch(localStorageProvider);
return AuthController(authAPI: authApi, userAPI: userApi, localStorage: localStorage);
});
As you can see it's a StateNotifierProvider, so inside AuthController sometimes i set state = false or state = true to say if it's loading or not.
Here's the definition of AuthController
class AuthController extends StateNotifier<bool> implements IAuthController {
// ....
void signupWithGoogle(....) {
state = true;
// do all the signup stuff
state = false;
}
}
In the VIEW, i can read the value of this state by using:
bool isLoading = ref.watch(authControllerProvider);
Problem:
But the problem is... How do i show a Dialog depending on this value? I tried putting in many places inside the code but all of them break somehow.
Last thing i tried (don't laugh cuz i already tried many things before this) was this:
@override
Widget build(BuildContext context) {
final isLoading = ref.watch(authControllerProvider);
if (isLoading) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showLoadingAnimation(context);
});
} else {
WidgetsBinding.instance.addPostFrameCallback((_) {
closeLoadingAnimation(context);
});
}
....
But with this approach the screen gets all black (without any error)
So what's the correct way of showing and closing a dialog in this case?
As I understood, you want a way to listen to provider state changes and update UI depending on it.
First of all, Use ref.read to call the function responsible for updating the state:
ref.read(authControllerProvider.notifier).updateState();
then in your build method:
ref.listen(authControllerProvider, (previous, next) {
if(next == true){
showDialog(context: context, builder: (_){
return Center(child: CircularProgressIndicator(),);
});
}else{
Navigator.pop(context);
}
});
In this way, each time state updated the listen function will triggered to give you prev and next state,
what I suggest for you, for loading process, don't show dialog, instead, do it using stack and visibility widget like this
@override
Widget build(BuildContext context) {
ref.watch(authControllerProvider);
return Scaffold(
body: Center(
child: Stack(
children: [
///your code
///
Visibility(
visible: ref.watch(authControllerProvider.notifier).state,
child: Center(
child: CircularProgressIndicator(),
),
)
],
),
),
);
}