A quick list of the Dart features that together make it indispensable for Flutter:
Dart is AOT (Ahead Of Time) compiled to fast, predictable, native code, which allows almost all of Flutter to be written in Dart. This not only makes Flutter fast, virtually everything (including all the widgets) can be customized.
Dart can also be JIT (Just In Time) compiled for exceptionally fast development cycles and game-changing workflow (including Flutter’s popular sub-second stateful hot reload).
Dart makes it easier to create smooth animations and transitions that run at 60fps. Dart can do object allocation and garbage collection without locks. And like JavaScript, Dart avoids preemptive scheduling and shared memory (and thus locks). Because Flutter apps are compiled to native code, they do not require a slow bridge between realms (e.g., JavaScript to native). They also start up much faster.
Dart allows Flutter to avoid the need for a separate declarative layout language like JSX or XML, or separate visual interface builders, because Dart’s declarative, programmatic layout is easy to read and visualize. And with all the layout in one language and in one place, it is easy for Flutter to provide advanced tooling that makes layout a snap.
Developers have found that Dart is particularly easy to learn because it has features that are familiar to users of both static and dynamic languages.
Compilation and execution
Computer languages have been divided into two groups:
static languages(e.g., Fortran or C, where variables are statically typed at compile time)
Static languages were typically compiled to produce native machine code (or assembly code) programs for the target machine, which at run time were executed directly by the hardware.
dynammic languages(e.g., Smalltalk or JavaScript, where the type of a variable can change at run time)
Dynamic languages were executed by an interpreter, without producing machine language code.
AOT vs JIT
When AOT compilation is done during development, it invariably results in much slower development. But AOT compilation results in programs that can execute more predictably and without pausing for analysis and compilation at runtime. AOT compiled programs also start executing faster(already been compiled).
Conversly, JIT compilation provides mush faster development cycles, but can result in slower or jerkier execution. In particular, JIT compilers have slower startup times, because when the program starts running the JIT compiler has todo analysis and compilation before the code can be executed.
Dart
Dart is one of very few languages (and perhaps the only "mainstream" language) that is well suited to being compiled both AOT and JIT. Supporting both kinds of compilation provides significant advantages to Dart and (especially) Flutter.
JIT compilation is used during development, using a compiler that is especially fast. Then, when an app is ready for release, it is compiled AOT.
extremely fast development cycles, and fast execution and startup times.
Dart can be efficiently compiled AOT or JIT, interpreted, or transpiled into other languages. Not only is Dart compilation and execution unusually flexible, it is especially fast.
Stateful hot reload
Avoiding jank
A fast app is great, but a smooth app is even better. Even a super fast animation will look bad if it is jerky. However, preventing jank can be difficult because there are so many different causes. Dart has a number of features to avoid many of the common things that cause jank.
Dart helps by being more predictable and giving the developer more control over the smoothness of their app, making it easier to provide the best user experience possible, bar none.
AOT compilation and the "bridge"
There is an even bigger advantage to AOT compiled code and that is avoiding the "Javascript bridge". When dynamic languages (like Javascript) need to interoperate with native code on the platform, they have to communicate over a bridge, which cause context switches that have to save particularly large amount of state. These context switches are double whammy because they not only slow things down, they can cause serious jank.
Preemptive scheduling, time slicing, and shared resources
Most computer languages that support multiple concurrent execution threads (including Java, Kotlin, Objective-C, and Swift) use preemptive to switch between threads. Each thread is allocated a "slice" of time to execute, and if exceeds its allocated time the thread is preempted using a context switch. However, if the preemption occurs when a resource that is shared between threads (like memory) is being updated, then this cause a race condition.
Race conditions are double whammy because they can cause serious bugs, including crashing your app and causing data to be lost, and they are particularly difficult to find and fix because they depend on the relative timing of independent threads.
The typical way to fix a race condition is to protect the shared resource using a lock that prevents other threads from executing, but locks themselves can cause jank, or even more serious problems(deadlock, starvation)
Dart took a different approach to this problem. Threads in Dart, called isolates, don't share memory, which avoids the need for most locks. Isolates communicate by passing messages over channels, which is similar to actors in Erlang or web workers in JavaScript.
Dart, like Javascript, is single thread, which means it does not allow preemption at all. Instead, threads explicitly yield (using async/await, Future, or Streams). This gives the developer more control over execution. Single threading helps the developer ensure that critical functions (including animations and transitions) are executed to completion, without preemption. This is often a big advantage not just for user interface, but for other client server code.
Allocation and garbage collection
Another serious cause of jank is garbage collection. Indeed, this is just a special case of accessing a shared resource (memory), which in many language requires the use of locks. But locks might stop the entire app from running while free memory is collected. However, Dart can perform garbage collection almost all of the time without locks.
Dart uses an advance generational garbage collection and allocation scheme, which is particularly fast for allocating many short-lived objects (perfect for every frame). Dart can allocate an object with single pointer bump (no lock required). Once again, this results in smooth scrolling and animation, with jank.
A quick list of the Dart features that together make it indispensable for Flutter:
Compilation and execution
Computer languages have been divided into two groups:
static languages(e.g., Fortran or C, where variables are statically typed at compile time)
dynammic languages(e.g., Smalltalk or JavaScript, where the type of a variable can change at run time)
AOT vs JIT
Dart
Stateful hot reload
Avoiding jank
AOT compilation and the "bridge"
Preemptive scheduling, time slicing, and shared resources
Allocation and garbage collection
Unified layout
Reference