“This is the 22nd day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

We have already had a general understanding of how Future works in Flutter. Are there any other task mechanisms in Flutter besides Future?

Let’s start with a piece of code:

void testFuture() {
  print('External code 1');
  Future(() => print('task A')).then((value) => print('A Mission completed '));
  Future(() => print('task B')).then((value) => print('B Mission completed '));
  print('External code 2');
}
Copy the code

Based on the usage and execution flow of the Future described in the previous article, we can easily guess the result:

So, if something urgent needs to be done first while the code is running, is there a way to handle it? That’s where microtasks come in;

scheduleMicrotask

ScheduleMicrotask is also called a microtask. Let’s modify the code and add a microtask to see what happens to the execution flow of the code. We modify the code as follows:

void testFuture() {
  print('External code 1');
  Future(() => print('task A')).then((value) => print('A Mission completed '));
  Future(() => print('task B')).then((value) => print('B Mission completed '));
  scheduleMicrotask(() {
    print('Microtask A');
  });
  sleep(const Duration(seconds: 1));
  print('External code 2');
}
Copy the code

ScheduleMicrotask has been added to the code execution flow, so what is the result of the code execution?

According to the printed information, we found that the scheduleMicrotask we added after the Future was executed first. ScheduleMicrotask has a higher priority, so we can also determine that there are two queues during the execution of this code, otherwise the microtask will not be executed first.

Queues in Dart

There are two pairs of classes that exist in Dart:

  • event queueEvent queue: This queue contains all extraneous events such asI/O,mouse events,drawing events,timersandIsolateInformation transfer between etc.;
  • microtask queueMicrotask queue: This queue represents an asynchronous task that will complete in a short period of time. It has the highest priority and can hog the event loop as long as there are tasks in the queue.microtask queueThe added tasks are mainly composed ofDartInternally generated.

Note that because the microTask Queue queue has a higher priority than the Event Queue queue, if there are too many microtasks in the MicroTask Queue, it is possible to hog the current Event loop. Thus, the touch, draw and other events in the Event queue will be affected, resulting in the blocking of these times.

During each event loop, Dart always checks the MicroTask Queue first to see if there are any available tasks. If there are no tasks in the MicroTask Queue, Dart processes the tasks and processes in the Event Queue.

In asynchronous tasks, we still use the low-priority Event queue most often. There is a layer of encapsulation in Dart for the tasks of the Event Queue, which is the Future we used earlier;

Dart asynchronous Future task execution process

  • Declare aFutureWhen,DartThe function execution body of the asynchronous task is put inevent queue, and immediately returns, and the subsequent code continues to execute synchronously;
  • When the synchronized code has finished executing,event queueIt takes out the events in the order they’re added in, the order they’re declared, and then synchronously executes themFutureFunction body and subsequent operations;

The event sample

Let’s define a list of tasks as follows:

void testFuture() {
  Future f1 = Future(() => null);
  f1.then((value) {
   print('6');
  }).then((value) => print('7'));

  Future f2 = Future(() => print('1'));
  f2.then((value){
    print('4');
  });

  Future(() => print('2'));

  scheduleMicrotask(() {
    print('3');
  });

  print('5');
}
Copy the code

According to our understanding of the Future task execution order, and scheduleMicrotask has a higher execution priority, its print order should be:

Five, three, six, seven, one, four, two

Let’s look at the print:

That’s exactly what we expected, so what if we changed the code as follows?

void testFuture() {
  Future f1 = Future(() => null);
  f1.then((value) {
   print('6');
   scheduleMicrotask(() {
     print('8');
   });
  }).then((value) => print('7'));

  Future f2 = Future(() => print('1'));
  f2.then((value){
    print('4');
  });

  Future(() => print('2'));

  scheduleMicrotask(() {
    print('3');
  });

  print('5');
}
Copy the code

We have added a microtask to the f1 task, so let’s look at the print result:

Looking at this result, we have to ask the question, right? ScheduleMicrotask is a microtask, so it should have the highest priority. Why is 8 printed after 7?

ScheduleMicrotask is also a microtask, but it is only in the microtask queue. The current microtask queue also prints 7, so 7 is printed before 8.