Question #297MediumAsync Programming

in initState fetchData func is calling that fetchData func as future.delayed(Duration(seconds: 2),(){

#state#future

Answer

Overview

This question covers calling an async function inside

text
initState
using
text
Future.delayed
and how to handle it correctly.


The Pattern

dart

void initState() {
  super.initState();
  fetchData(); // ✅ Call async function without await
}

Future<void> fetchData() async {
  await Future.delayed(Duration(seconds: 2), () {
    // This runs after 2 seconds
    setState(() {
      _data = 'Loaded!';
    });
  });
}

Why Not Use await in initState?

text
initState
is a synchronous method — you cannot mark it
text
async
or use
text
await
directly.

dart
// ❌ Wrong — initState cannot be async

Future<void> initState() async {
  super.initState();
  await fetchData(); // Error!
}

// ✅ Correct — call async function, don't await it

void initState() {
  super.initState();
  fetchData(); // Fire and forget (Dart handles it)
}

Full Working Example

dart
class DataScreen extends StatefulWidget {
  
  _DataScreenState createState() => _DataScreenState();
}

class _DataScreenState extends State<DataScreen> {
  String _data = '';
  bool _isLoading = true;

  
  void initState() {
    super.initState();
    fetchData(); // ✅ Called without await
  }

  Future<void> fetchData() async {
    // Simulate a 2-second API call
    await Future.delayed(Duration(seconds: 2), () {
      if (mounted) { // ✅ Always check mounted before setState
        setState(() {
          _data = 'Data Loaded Successfully!';
          _isLoading = false;
        });
      }
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Data Screen')),
      body: Center(
        child: _isLoading
            ? CircularProgressIndicator()
            : Text(_data, style: TextStyle(fontSize: 20)),
      ),
    );
  }
}

Why Check
text
mounted
?

If the user navigates away before the 2 seconds complete, the widget is disposed. Calling

text
setState
on a disposed widget throws an error.

dart
Future<void> fetchData() async {
  await Future.delayed(Duration(seconds: 2));

  // ✅ Always check mounted before setState after an await
  if (mounted) {
    setState(() => _data = 'Loaded');
  }
}

Future.delayed Signatures

dart
// With callback — runs the callback after duration
await Future.delayed(Duration(seconds: 2), () {
  setState(() => _data = 'Done');
});

// Without callback — just waits, then continues
await Future.delayed(Duration(seconds: 2));
setState(() => _data = 'Done');

Common initState Async Patterns

dart

void initState() {
  super.initState();

  // Pattern 1: Direct call
  fetchData();

  // Pattern 2: With error handling
  fetchData().catchError((e) => print('Error: $e'));

  // Pattern 3: Using Future.microtask for post-build access
  Future.microtask(() => fetchData());

  // Pattern 4: Using WidgetsBinding for after-frame callback
  WidgetsBinding.instance.addPostFrameCallback((_) => fetchData());
}

When to Use Each Pattern

PatternUse When
text
fetchData()
directly
Simple async call, no dependencies on layout
text
Future.microtask(fetchData)
Need to call after initState fully completes
text
addPostFrameCallback(fetchData)
Need layout/size info (like MediaQuery) available
text
Future.delayed(duration)
Intentional delay (splash screen, retry, demo)

Best Practice: Always check

text
if (mounted)
before calling
text
setState
after any
text
await
in a StatefulWidget. This prevents the "setState called on a disposed widget" error.