Original address: medium.com/dartlang/da…

Author: Medium.com/kathyW_392…

Published: July 26, 2019-5 minutes to read

Although Dart is a single-threaded language, it provides support for futures, flows, background work, and everything else you need to write in a modern, asynchronous, and (in the case of Flutter) reactive manner. This article introduced the foundation of Dart support for background work: isolation and event loops. If you like to learn by watching or listening, everything in this article will be covered in the following video, part of the Asynchronous Programming in Dart video series, Flutter in Focus.

www.youtube.com/watch?v=vl_…

Still here? Let’s talk about containment.


spacer

The quarantine is where all the Dart code runs. It’s like a small space on a machine, with its own private memory and a single thread running an event loop.

A quarantine has its own memory and a thread of execution that runs the event loop.

In many other languages, such as C++, you can have multiple threads sharing the same memory and running any code you want. But in Dart, each thread has its own memory in its own isolation, and the thread just handles events (more on that later).

Many Dart applications run all of their code in one quarantine, but you can have multiple quarantines if you need to. If the calculation you are performing is very large and might cause you to drop frames if you run it in primary isolation, you can use the isolate.spawn () or compute() function of Flutter. Both of these functions create a separate quarantine for numeric operations, leaving your main quarantine free to, say, rebuild and render the Widget tree.

Two isolation bodies, each with its own memory and thread of execution.

The new isolation body has its own event loop and its own memory, which the original isolation body — although it is the parent of the new isolation body — does not allow access to. This is where the name insular comes from: these small Spaces are kept isolated from each other.

In fact, the only way isolators can work together is by passing messages back and forth. One quarantine body sends a message to another, and the receiving quarantine body uses its event loop to process the message.

Quarantines can send messages to other quarantines.

This lack of shared memory may sound a bit strict, especially if you come from a language like Java or C++, but it has some key benefits for Dart coders.

For example, memory allocation and garbage collection in quarantine do not require locking. There’s only one thread, so if it’s not busy, you know memory hasn’t been mutated. This is good for Flutter applications, which sometimes require a bunch of parts to be built and dismantled quickly.


Event loop

Now that you have a basic introduction to isolators, let’s dive into what really makes asynchronous code possible: event loops.

Imagine the life of an application stretching out on a timeline. The application starts, the application stops, and a bunch of events happen — I/O from the disk, the user’s finger hits…… All kinds of things.

Your application cannot predict when these events will occur or in what order; it must handle them all with a single thread that never blocks. So, the application runs an event loop. It grabs the oldest event from its event queue, processes it, goes back to the next one, processes it, and so on until the event queue is empty.

As the app runs — you’re clicking on the screen, things are downloading, timers go off — the event loop keeps going round and round, processing these events over and over again.

The event loop handles one event at a time.

When the action is interrupted, the thread is suspended, waiting for the next event. It can trigger the garbage collector, go for coffee, etc. All of the advanced APIS and language features Dart provides for asynchronous programming — futures, flows, asynchrony, and wait — are built on top of and around this simple loop.

For example, suppose you have a button that initiates a network request, like this one.

RaisedButton(
  child: Text('Click me'),
  onPressed: () {
    final myFuture = http.get('https://example.com');
    myFuture.then((response) {
      if (response.statusCode == 200) {
        print('Success! '); }}); },)Copy the code

When you run your app, Flutter creates this button and places it on the screen. Then your application waits. Your application’s event loop is just a little idle, waiting for the next event. Events unrelated to the button might come in and get processed, while the button sits there waiting for the user to click on it. Eventually they clicked, and a click event entered the queue.

This event is received for processing. Flutter looks and the rendering system says “these coordinates match the raised button”, so Flutter executes onPressed. This code initiates a network request (which returns a future) and registers a completion handler for the Future by using the THEN () method.

That’s it. The loop completes processing the TAP event and discards it.

Right now, onPressed is a property of RaisedButton, and the network event uses a Future callback, but both techniques do the same basic thing. They’re all telling Flutter, “Hey, later on, you might see a certain type of event coming in. When you see it, execute this code.

So, onPressed is waiting for a knock, and the future is waiting for network data, but from Dart’s point of view, these are just events in a queue.

That’s how asynchronous coding works in Dart. Future, flow, async, wait — these apis just let you tell Dart’s event loop: “Here’s some code, please run it later.”

If we look back at the code example, you can now see how it is broken up into event-specific chunks. There are initial build events (1), knock events (2), and network response events (3).

RaisedButton( // (1) child: Text('Click me'), onPressed: () { // (2) final myFuture = http.get('https://example.com'); myFuture.then((response) { // (3) if (response.statusCode == 200) { print('Success! '); }}); },)Copy the code

As you get used to using asynchronous code, you’ll start to recognize all of these patterns. As you move on to higher-level apis, it will help to understand the event loop.


conclusion

We quickly learned about isolation, event loops, and the basics of asynchronous coding in Dart. If you want more details on how microtask queues work, see the outdated, archived, but still popular article event Loops and Dart.

To learn more about asynchrony in Dart, check out the next article in this series, Dart Asynchronous Programming: Future.

Many thanks to Andrew Brogdon, who created the video on which this article is based.


www.deepl.com translation