Anmol Singh

Web & Flutter Developer

How Flutter Programs Run Under the Hood: Simply Explained

• 4 min read

Flutter applications are built using the Dart programming language. Dart is a free, open-source, object-oriented language developed by Google. One of its key strengths is cross-platform development.

This means you can write code once and deploy it on various platforms like mobile (Android, iOS), desktop (Windows, macOS, Linux), and even the web — all with near-native performance. This is achieved by compiling Dart code into machine code specific to the target platform.

Another key feature of Dart is its ability to make changes iteratively and quickly which is done through the use of the hot-reload feature. This feature allows you to see the result instantly in your running app.

The power of making changes on the fly is what we’ll be diving deep into today. Let’s see how dart code is transitioned into an app in the first place. But for that, we first need to understand a few terms.

1. Dart compiler:

The Dart compiler is a specific tool used to translate Dart code into either machine code or bytecode. Bytecode is a low-level code that is the result of the compilation(translation) of a source code which is written in a high-level language (Dart). It is processed by a virtual machine like Dart Virtual Machine (Dart VM) discussed below.

Types of Compilation:

a) Ahead-of-Time (AOT) Compilation: This process translates the entire Dart codebase into machine code specific to the target platform (like ARM for mobile devices). This is typically used for release builds in Flutter to achieve potentially better performance and smaller app size compared to JIT.

b) Just-in-Time Compilation (JIT): This is the primary technique used by Dart VM for compiling dart code on the fly. It translates small chunks of Dart code into bytecode (an intermediate representation of code) just before they are needed for execution by Dart VM. This approach allows for faster development cycles with features like hot reload in Flutter.

c) Dart to JavaScript Compilation: The Dart compiler, specifically dart2js, is used to translate Dart code into a combination of JavaScript and WebAssembly for web development.

Flutter provides three main build modes that determine how the Dart code is compiled and optimized for different purposes:

Debug Mode:
Profile Mode:
Release Mode:
2. Dart Virtual Machine:

The Dart VM is the primary execution engine or interpreter for Dart code. It’s not a physical machine but a software layer that provides an environment for Dart programs to run. It acts as an intermediary between your Dart code and the underlying hardware (processor, memory) of your device. The Dart VM mainly uses Just-in-Time Compilation (JIT) for code execution.

Some of the other responsibilities of Dart VM include:

It is possible for hot reload to work because of JIT. It is so because the Dart VM can efficiently update only the modified parts of the code with the newly JIT-compiled bytecode. This allows the app to reflect the changes almost instantly without a full restart.

For AOT compilation, especially in release builds, a common approach is hot restart. This involves restarting the entire app with the newly compiled machine code after code changes are made. While not as instantaneous as hot reload with JIT, hot restart provides a way to test changes in a more optimised environment (AOT) without requiring a full app rebuild from scratch.

Now let’s see how it works practically. When you write Dart code and run it, several processes occur depending on the development stage and compilation mode you’re using. Here’s a breakdown of the major phases:

1. Development Time:

2. Compile Time:

3. Runtime:

Conclusion

Flutter’s ability to run programs efficiently across multiple platforms is a testament to the powerful combination of the Dart programming language, the Dart compiler, and the Dart Virtual Machine. The seamless integration of Just-in-Time (JIT) compilation for rapid development cycles and hot reload, along with the option for Ahead-of-Time (AOT) compilation for optimized performance and smaller app sizes, caters to the diverse needs of developers throughout the app development lifecycle.