Async Controller

An Async Controller is a special variable type that manages async state and cache invalidation when used with Future Builder. It prevents unnecessary retrieval when rebuilds occur and provides a way to force refresh async data when needed.

Supported Widgets

The Async Controller can be used with:

  • Future Builder

When to Use

Use an Async Controller when you need to:

  • Prevent Future Builder from refetching data on every rebuild

  • Implement manual refresh functionality (pull-to-refresh)

  • Force cache invalidation for async data

  • Control when expensive async operations should re-run

  • Optimize performance by caching async results

Creating an Async Controller

  1. Navigate to Variables in your project

  2. Click Add Variable

  3. Select Async Controller as the type

  4. Give it a descriptive name (e.g., userDataController, productsController)

How It Works

Without Async Controller

When a Future Builder rebuilds (e.g., due to state changes elsewhere on the page), it will re-execute its future/async operation every time, potentially making unnecessary API calls.

With Async Controller

When you bind an Async Controller to a Future Builder:

  • First build: The future executes normally

  • Subsequent rebuilds: The cached result is used, and the future does NOT re-execute

  • After invalidate(): The cache is cleared, and the next rebuild will re-execute the future

This gives you fine-grained control over when data is fetched.

Binding to Widgets

Future Builder Example

Controller Methods

Use the Control Object action to invoke this method on the controller.

invalidate

Forces a re-evaluation or refresh of the Future Builder's data by clearing the cache.

No parameters required.

When to Use:

  • User pulls to refresh

  • User clicks a "Refresh" button

  • Data becomes stale and needs to be refetched

  • After making changes that affect the async data (e.g., updating a profile)

Example:

After calling invalidate(), the Future Builder will re-execute its future the next time it builds.


Common Use Cases

1. Pull-to-Refresh

Implement pull-to-refresh functionality without unnecessary data fetching.

Setup:

Implementation:

2. Manual Refresh Button

Add a refresh button that refetches data on demand.

Setup:

3. Refresh After Mutation

Invalidate cache after updating data to ensure UI shows latest changes.

Setup:

On Edit Page:

4. Preventing Unnecessary API Calls

Optimize performance by caching async results across rebuilds.

Problem Without Controller:

Solution With Controller:

5. Conditional Refresh

Invalidate only when certain conditions are met.

6. Multiple Data Sources with Independent Refresh

Use separate controllers for independent data sources.

Best Practices

  • One controller per async data source: Create separate controllers for independent data sources

  • Use descriptive names: Name controllers after the data they manage (userDataController, productsController)

  • Invalidate after mutations: Always invalidate after updating data to keep UI in sync

  • Combine with loading states: Show loading indicators while data is being fetched

  • Handle errors: Ensure Future Builder handles error states gracefully

  • Don't over-invalidate: Only invalidate when data actually needs to be refreshed

  • Consider stale time: For data that changes rarely, avoid frequent invalidation

Common Patterns

Basic Invalidation

Invalidate and Show Loading

Invalidate After Success

Conditional Invalidation

Invalidate Multiple Controllers

Performance Benefits

Without Async Controller

With Async Controller

Troubleshooting

Controller Not Working

  • Ensure the controller variable is properly created

  • Check that the controller is bound to Future Builder using ${controllerName}

  • Verify the widget supports Async Controller

Data Not Refreshing After Invalidate

  • Ensure invalidate() is being called correctly

  • Check that the Future Builder is actually rebuilding after invalidation

  • Verify the future/API call is configured correctly

Data Still Refetching on Every Rebuild

  • Confirm the controller is properly bound to the Future Builder

  • Check that you're using the controller correctly in expressions

Last updated