A Try Again Button
Part of the Data and the Network section of Coddy's Flutter journey. Lesson 14 of 27.
Connections come back. A good error screen does not leave the person stuck: it says what happened and offers a way to try again.
Trying again is a reload: make a new future in setState, the same as a refresh button.
void tryAgain() {
setState(() {
_message = fetch('/message');
});
}One detail. While the new future runs, the snapshot keeps the last error, the way it keeps old data: hasError stays true until the new answer arrives. To show the spinner during the second try, check snapshot.connectionState first:
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
if (snapshot.hasError) {
// the error and the button
}
return Text(snapshot.data!);To see it fail in the preview, write offline = true; as the first line of main and press Run. offline comes from api.dart: it makes every call fail as if the phone had no signal. Take the line out before you press Check.
Challenge
MediumGive the error state a way out:
- under the error text, add a Try again button
- pressing it sets a new
fetch('/message')insetState - the spinner shows while it tries again: check
ConnectionState.waitingfirst in the builder
Try it yourself
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: MessageScreen(),
);
}
}
class MessageScreen extends StatefulWidget {
const MessageScreen({super.key});
@override
State<MessageScreen> createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
late Future<String> _message;
@override
void initState() {
super.initState();
_message = fetch('/message');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<String>(
future: _message,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text(
'Could not load: ${snapshot.error}',
style: const TextStyle(fontSize: 20),
);
}
if (snapshot.hasData) {
return Text(snapshot.data!, style: const TextStyle(fontSize: 24));
}
return const CircularProgressIndicator();
},
),
),
);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Data and the Network
3When Calls Fail
Catching Errors With tryThrowing an ErrorCleaning Up With finallyThe FutureBuilder Error StateA Try Again ButtonPractice on your own: Online Flutter compiler