On this page
Async and Futures
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
- Read the full error in the console.
- Use Flutter DevTools widget inspector.
- Hot restart vs hot reload — know the difference.
- Check null safety and type errors first.
- 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
- Explain the core concept of this topic in your own words.
- What happens when this code runs with edge-case input (empty, null, zero, max value)?
- How would you debug a bug related to this topic in production?
- What are the performance implications of the approach shown here?
- How does this feature compare to the equivalent in another language you know?