Completers In Flutter

a Completer lets you control when a Future is completed and its result becomes available.

Shirsh Shukla
5 min readAug 13, 2024

In this article, we will dive deep into Completers in Flutter. We will discuss what a Completer is and its purpose in Flutter. A Completer is an object used to manually complete a Future. When you create a Future, it represents a value that will be available at a later time. To manage this manually, we use a Completer. To better understand this, let’s look at an example.

Imagine you’re ordering an item from an e-commerce app. After placing the order, you wait for the product to be delivered to your doorstep. In this scenario, the package you ordered represents the Future, and the person delivering it is the Completer.

The delivery person, like the Completer, has an app to complete the task of delivery. When the delivery person arrives at your doorstep, they mark the product as delivered, ask for the OTP, and confirm the delivery. This confirmation updates the status of the Future in your app, thanks to the Completer.

This is how a Completer works in Flutter. So now we understand that,

In Flutter, a Completer is a way to manually control the completion of a Future. A Future is like a promise that something will be done later, and a Completer lets you decide exactly when that promise is fulfilled.

Now let’s take a simple flutter example of how Completer works,

Imagine you have a button in your app that, when pressed, starts a long-running task like fetching data from the internet. You want to show a loading indicator while the task is running and hide it once the task is done.

Here’s how you can use a Completer to manage this:

How It Works:

  1. Completer Initialization: When the app starts, a Completer is created in the initState method.
  2. Starting the Task: When you press the button, the _startTask method is called. This method creates a new Completer and starts a simulated long-running task using Future.delayed.
  3. Completing the Task: After 3 seconds, the task is done and _completer.complete() is called. This tells them Completer that the task is finished.
  4. Updating the UI: The FutureBuilder listens to the Completer's Future. While the task is running, it shows a loading indicator (CircularProgressIndicator). Once the task is complete, it updates the UI to show "Task Completed!"

This is how a Completer helps you control when a Future is marked as complete, which in turn helps you manage the UI or other actions based on the completion of asynchronous tasks.

So now we know about what is Completer also, we understand how it works, so our next challenge is when to use Completer or when to use Future .

let’s dive a bit deeper into the differences while keeping it simple.

1. When to Use Completer:

Think of Completer like a Remote Control:

  • Imagine you have a remote control that can pause and play a video. You decide when to press play and when to press pause. The video won’t play until you press the button.
  • Example: You’re writing a Flutter app where you want to show a loading spinner until a user clicks a button. You don’t know when the user will click it, so you need a way to wait for that event. This is where a Completer comes in handy—you can start the loading spinner and then use the Completer to stop it only when the user clicks the button.

Why Use Completer?

  • Flexibility: You control exactly when a task is considered done. It’s like being the director of a movie, saying “Cut!” when you’re ready to end the scene.
  • Multiple Conditions: Sometimes, you need several things to happen before you can finish a task. With a Completer, you can wait for all those things to happen before you declare the task done.

2. When to Use Future:

Think of Future like a Timer:

  • Imagine setting a timer to boil an egg. You know that after 5 minutes, the egg will be boiled, and the timer will automatically ring. You don’t need to do anything special — the timer will let you know when it’s done.
  • Example: In Flutter, when you make an HTTP request to get data from the internet, the request starts immediately, and the Future will automatically tell you when the data is received. You don’t need to manually control when it’s done because the process is straightforward.

Why Use Future?

  • Simplicity: If you don’t need special control over when something finishes, using a Future is easier. It’s like a self-driving car—it handles the journey and just lets you know when you’ve arrived.
  • Built-In Asynchronous Operations: Many built-in functions in Flutter, like fetching data from the internet or reading files, already return a Future. You just use it as is because it’s designed to handle the task for you.

Let’s add some simple code examples to illustrate when to use Completer versus Future.

1. Using Completer:

Scenario: You want to start a loading spinner and stop it when the user clicks a button.

Code Example:

Explanation:

  • Completer Creation: We create a Completer in initState.
  • Completing the Task: The FloatingActionButton calls _completeTask, which marks the Completer as complete.
  • UI Update: FutureBuilder listens to _completer.future and shows a spinner until _completer.complete() is called.

2. Using Future:

Scenario: You want to delay a task for 3 seconds and then show a message.

Code Example:

Explanation:

  • Starting the Task: The _startTask method creates a Future that completes after 3 seconds using Future.delayed.
  • UI Update: FutureBuilder listens to _delayedTask and shows a spinner until the future completes automatically.

In the Completer example, you manually decide when the task is done, while in the Future example, the task finishes automatically after a delay.

In Conclusion, a Completer is a tool that gives you the ability to manually control when a task is completed. Think of it as having a remote control for finishing a task. You use a Completer when you need to wait for something specific to happen, like waiting for a user to press a button or for multiple conditions to be met before finishing the task. This is useful when the completion of a task depends on various factors that you control.

In contrast, a Future is more like a timer that automatically finishes on its own. For example, when you make a network request or set a delay, a Future handle the timing and completion of these tasks without needing manual control. It’s simpler to use when the start and end of the task are straightforward and automatic.

So, in one line, use a Completer when you need to decide exactly when a task is done, and use a Future for tasks that automatically handle their own completion.

If you got something wrong? Mention it in the comments. I would love to improve. your support means a lot to me! If you enjoy the content, I’d be grateful if you could consider subscribing to my YouTube channel as well.

I am Shirsh Shukla, a creative Developer, and a Technology lover. You can find me on LinkedIn or maybe follow me on Twitter or just walk over my portfolio for more details. And of course, you can follow me on GitHub as well.

Have a nice day!🙂

--

--

Shirsh Shukla

SDE at Reliance Jio | Mobile Application Developer | Speaker | Technical Writer | community member at Stack Overflow | Organizer @FlutterIndore