FutureBuilder: Handling Async UI in Flutter
FutureBuilder rebuilds UI based on an async operation's state, showing loading, error, or data. Use it for network requests or slow computations. Footgun: Never create the Future inside `build`; it will restart on every rebuild, causing an infinite loading…
WHY IT EXISTS Flutter's UI is declarative and rebuilds frequently. Manually managing state from async operations like API calls with setState can be complex and error-prone. You need a way to connect the lifecycle of a one-off async task directly to a specific piece of the UI tree, letting it rebuild itself automatically.
THE MENTAL MODEL Think of FutureBuilder as a state machine for a part of your UI. You give it a task (the Future) and instructions (the builder function) for what to display in each state: 'task running,' 'task succeeded,' or 'task failed.' It handles the setState calls internally to trigger rebuilds as the task progresses, so you don't have to.
HOW IT WORKS FutureBuilder takes a future and a builder function. This builder receives an AsyncSnapshot object. You check the snapshot.connectionState. If it's ConnectionState.waiting, you return a loading indicator. If it's ConnectionState.done, the future is complete. You then check snapshot.hasError. If true, display an error widget using snapshot.error. If false, display your main widget using the successful result from snapshot.data.
WHEN TO USE IT Use FutureBuilder whenever a UI component depends on the result of a single asynchronous operation that won't be repeated. This is perfect for fetching user profile data when a screen loads, reading initial configuration from a file, or running a one-time calculation that would otherwise block the UI thread.
WHEN NOT TO USE IT Do not use FutureBuilder for continuous streams of data that emit multiple values over time, like a WebSocket connection or live database updates. For that, use its sibling, StreamBuilder. More importantly, do not use it if you are creating the Future object inside the build method.
ONE CANONICAL EXAMPLE The most common mistake is creating the Future inside the build method, which causes it to re-run on every rebuild. WRONG: FutureBuilder(future: http.get(...), builder: ...) This creates an infinite loop of network requests and loading spinners. RIGHT: In a StatefulWidget, declare the Future as a member variable and initialize it once inside initState. late Future<Album> futureAlbum; @override void initState() { super.initState(); futureAlbum = fetchAlbum(); } Then, in the build method, pass this stateful variable: FutureBuilder<Album>(future: futureAlbum, builder: ...) This ensures the async operation runs only once when the widget is first inserted into the tree.
Read the original → api.flutter.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.