Dart’s async model uses Future for single values and Stream for sequences. async/await makes async code read like synchronous code.

Future

  Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 1));
  return 'Data loaded';
}

void main() async {
  final data = await fetchData();
  print(data);
}
  

Error Handling

  Future<void> load() async {
  try {
    final result = await riskyOperation();
    print(result);
  } catch (e) {
    print('Error: $e');
  } finally {
    cleanup();
  }
}
  

Streams

  Stream<int> countStream() async* {
  for (int i = 1; i <= 5; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

await for (final val in countStream()) {
  print(val);
}
  

Future.wait

  final results = await Future.wait([
  fetchUser(),
  fetchPosts(),
  fetchComments(),
]);
  

StreamController

  final controller = StreamController<String>();
controller.stream.listen((data) => print(data));
controller.add('event');
controller.close();
  

Common Pitfalls

  • Ignoring null safety warnings and using ! operator carelessly.
  • Calling setState excessively causing unnecessary rebuilds.
  • Mixing async patterns without proper error handling.
  • Hardcoding values that should be theme constants.

Best Practices

  • Prefer const constructors for static widgets.
  • Use named parameters for widget constructors.
  • Extract reusable widgets into separate files.
  • Write widget tests for critical UI paths.

Memory and Performance Notes

Each await yields to event loop. Don’t block isolate with CPU-heavy sync work.

Exercise

Fetch data from a public API using http package. Display loading, error, and success states.

Hint: Use flutter pub add http. Handle SocketException for network errors.

Summary

Practice with Flutter DevTools open to observe rebuilds and performance.

Debugging Checklist

  1. Read the full error in the console.
  2. Use Flutter DevTools widget inspector.
  3. Hot restart vs hot reload — know the difference.
  4. Check null safety and type errors first.
  5. Simplify widget tree to isolate the issue.

Real-World Application

Production Flutter apps combine these patterns with analytics, crash reporting, and CI/CD.

Further Reading

Flutter documentation, Dart language tour, and pub.dev packages.

Additional Examples

Consider how this topic applies in a larger project:

  // Break the problem into smaller functions
// Test each function independently
// Integrate incrementally
  

Working through variations of the examples above builds deeper understanding than reading alone.

Interview and Review Questions

  1. Explain the core concept of this topic in your own words.
  2. What happens when this code runs with edge-case input (empty, null, zero, max value)?
  3. How would you debug a bug related to this topic in production?
  4. What are the performance implications of the approach shown here?
  5. How does this feature compare to the equivalent in another language you know?