CodeBlanks Logo Icon CodeBlanks

Summary - FutureBuilder

Combine FutureBuilder and snapshot to make a data screen.

Summary - FutureBuilder

In this section you learned three things: with FutureBuilder you bind a Future to the UI; with AsyncSnapshot you access connectionState and data; with waiting and hasError you handle loading and error states.

FutureBuilder<String>(
  future: _future,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    }
    return Text(snapshot.data ?? 'empty');
  },
)

Combining these, you build a data screen.

Practice Build a data screen

The veriGetir async method should wait 100 ms and return 'Veri hazır'. In Ekrani stateful widget, hold a _future field, call print('ekran açıldı') in initState and assign _future = veriGetir(). In FutureBuilder<String>: while waiting show CircularProgressIndicator, if hasError show Text('hata'), otherwise show Text(snapshot.data!). Start the app in main.

Starter code

main.dart
import 'package:flutter/material.dart';

Future<String> veriGetir() async {
  await Future.delayed(Duration(milliseconds: 100));
  return 'Veri hazır';
}

class Ekrani extends StatefulWidget {
  @override
  _EkraniState createState() => _EkraniState();
}

class _EkraniState extends State<Ekrani> {
  // _future field ekle
  // initState: print ve future'ı başlat

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('bekle')),
    );
  }
}

void main() => runApp(MaterialApp(home: Ekrani()));

Sample solution

main.dart
import 'package:flutter/material.dart';

Future<String> veriGetir() async {
  await Future.delayed(Duration(milliseconds: 100));
  return 'Veri hazır';
}

class Ekrani extends StatefulWidget {
  @override
  _EkraniState createState() => _EkraniState();
}

class _EkraniState extends State<Ekrani> {
  late Future<String> _future;

  @override
  void initState() {
    super.initState();
    print('ekran açıldı');
    _future = veriGetir();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder<String>(
          future: _future,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            } else if (snapshot.hasError) {
              return Text('hata');
            }
            return Text(snapshot.data!);
          },
        ),
      ),
    );
  }
}

void main() => runApp(MaterialApp(home: Ekrani()));

Expected output

ekran açıldı

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 How do we detect loading state in FutureBuilder?

  • snapshot.hasError
  • snapshot.data == null
  • snapshot.connectionState == ConnectionState.none
  • snapshot.connectionState == ConnectionState.waiting Correct answer

Explanation: ConnectionState.waiting indicates that the Future has not completed yet and is in loading phase.

2 Bind FutureBuilder's future parameter

Question
FutureBuilder<String>(
  future: ____,
  builder: (context, snapshot) => Text('?'),
)
Answer
FutureBuilder<String>(
  future: _future,
  builder: (context, snapshot) => Text('?'),
)

Explanation: FutureBuilder's future parameter takes the Future to watch; usually the _future variable in state.

3 FutureBuilder section parts

Term Meaning
FutureBuilder Widget binding Future to UI
AsyncSnapshot Carries Future's current state
ConnectionState.waiting Loading phase
hasError Property indicating error state

All lessons in Intermediate