Menu
Coddy logo textTech

Async in Class Methods

Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 80 of 110.

Now that you know how to handle async initialization with factory methods, let's look at making regular instance methods asynchronous. This is straightforward - just add async to any method and have it return a Future.

class WeatherService {
  String _location;
  
  WeatherService(this._location);
  
  Future<String> fetchTemperature() async {
    await Future.delayed(Duration(seconds: 1));
    return '22°C in $_location';
  }
  
  Future<void> updateLocation(String newLocation) async {
    await Future.delayed(Duration(milliseconds: 500));
    _location = newLocation;
    print('Location updated to $_location');
  }
}

Future<void> main() async {
  var service = WeatherService('London');
  var temp = await service.fetchTemperature();
  print(temp);
  
  await service.updateLocation('Paris');
}

Async methods can access and modify instance variables just like regular methods. The key difference is that callers must await the result. Methods returning Future<void> don't return a value but still need to be awaited if you want to ensure they complete before continuing.

You can also combine multiple async calls within a method, or call other async methods from the same class:

Future<String> getFullReport() async {
  var temp = await fetchTemperature();
  var humidity = await fetchHumidity();
  return '$temp, Humidity: $humidity';
}

This pattern is essential for classes that interact with external resources - APIs, databases, or any operation that takes time.

challenge icon

Challenge

Easy

Let's build a stock portfolio tracker that manages stock prices and calculates portfolio values using async methods! You'll create a class that simulates fetching real-time stock data and combines multiple async operations to generate reports.

You'll organize your code into two files:

  • portfolio.dart: Create a StockPortfolio class that tracks stocks and their quantities. Your class should have:
    • A private Map<String, int> called _holdings that stores stock symbols and the number of shares owned
    • A constructor that initializes _holdings as an empty map
    • A method addStock(String symbol, int quantity) that adds or updates a stock holding (not async)
    • An async method fetchPrice(String symbol) that returns a Future<double>. Simulate a delay of 50 milliseconds, then return a price calculated as: the length of the symbol multiplied by 25.5
    • An async method getStockValue(String symbol) that returns a Future<double>. This should await fetchPrice for the symbol, multiply by the quantity held, and return the total value. If the symbol isn't in holdings, return 0.0
    • An async method getTotalValue() that returns a Future<double>. This should calculate the combined value of all holdings by awaiting getStockValue for each stock and summing the results
    • An async method generateReport() that returns a Future<String>. This should build a report showing each stock's value and the total. Format each line as [symbol]: $[value] (value with 1 decimal place), followed by a final line Total: $[totalValue] (also 1 decimal place)
  • main.dart: Import your portfolio file and demonstrate how async methods work together within a class:
    • Create a StockPortfolio instance
    • Add these holdings: AAPL with 10 shares, GOOGL with 5 shares, MSFT with 8 shares
    • Print Fetching portfolio data...
    • Await and print the result of generateReport()

Notice how generateReport() calls other async methods within the same class, and how each method builds upon the others. Use toStringAsFixed(1) to format decimal values!

Expected output:

Fetching portfolio data...
AAPL: $1020.0
GOOGL: $637.5
MSFT: $816.0
Total: $2473.5

Cheat sheet

To make instance methods asynchronous, add the async keyword and return a Future:

class WeatherService {
  String _location;
  
  WeatherService(this._location);
  
  Future<String> fetchTemperature() async {
    await Future.delayed(Duration(seconds: 1));
    return '22°C in $_location';
  }
  
  Future<void> updateLocation(String newLocation) async {
    await Future.delayed(Duration(milliseconds: 500));
    _location = newLocation;
    print('Location updated to $_location');
  }
}

Async methods can access and modify instance variables. Callers must await the result. Methods returning Future<void> don't return a value but still need to be awaited to ensure completion.

Async methods can call other async methods within the same class:

Future<String> getFullReport() async {
  var temp = await fetchTemperature();
  var humidity = await fetchHumidity();
  return '$temp, Humidity: $humidity';
}

This pattern is essential for classes that interact with external resources like APIs or databases.

Try it yourself

import 'portfolio.dart';

void main() async {
  // TODO: Create a StockPortfolio instance

  // TODO: Add holdings:
  // - AAPL with 10 shares
  // - GOOGL with 5 shares
  // - MSFT with 8 shares

  // TODO: Print "Fetching portfolio data..."

  // TODO: Await and print the result of generateReport()
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming