I made a function to show a loading dialog while a Future is doing its computation, and automatically dismiss the dialog when the Future completes. To achieve this, I put a try-catch block inside a Future in the builder function like this:
Future<T?> showLoadingDialog<T>({
required BuildContext context,
required Future<T> future,
}) {
return showDialog<T>(
context: context,
builder: (context) {
Future(() async {
try {
final value = await future;
if (context.mounted) {
Navigator.of(context).pop(value);
}
} catch (_) {
Navigator.of(context).pop();
rethrow;
}
});
return Dialog(
// ...
);
},
// ...
);
}
I want the caller function (for example, a function inside a StatefulWidget that is trying to get the result value from the dialog) to be able to catch error thrown by the Future. This is an example of where the function is called:
class LoginForm extends ConsumerStatefulWidget {
const LoginForm({super.key});
@override
ConsumerState<ConsumerStatefulWidget> createState() => _LoginFormState();
}
class _LoginFormState extends ConsumerState<LoginForm> {
final emailController = TextEditingController();
final passwordController = TextEditingController();
@override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
Future<void> login() async {
final httpClient = ref.read(httpClientProvider);
try {
final response = await showLoadingDialog(
context: context,
future: httpClient.post('/login', data: {
'email': emailController.text,
'password': passwordController.text,
}),
);
// should not reach here
} on DioException catch (e) {
// should catch here
}
}
// ...
}
Even though I put rethrow in the catch block inside the showDialog's builder function, the caller function can't catch the error. What happened is the function still continue to execute lines after the showLoadingDialog call in the try block and the error is not caught.