Ralfiz Academy
Free lesson · Flutter 0.1

Flutter and Dart: the big picture

Flutter is Google’s open-source UI toolkit for building apps for Android, iOS, web, Windows, macOS and Linux from one codebase. You write the app in Dart, a typed language that compiles to fast…

About 40 minutesDeveloper courseStart here

At a glance

9 min read

Flutter is Google’s open-source UI toolkit for building apps for Android, iOS, web, Windows, macOS and Linux from one codebase. You write the app in Dart, a typed language that compiles to fast native machine code for release builds and supports hot reload while you develop.

Flutter does not wrap the platform’s own buttons and lists. It draws every pixel itself with its own rendering engine, so your app looks the same everywhere. You describe the screen as a tree of widgets; when data changes, Flutter rebuilds the widgets and repaints only what changed.

In this track you learn Dart first, then Flutter layout, theming, navigation, state management (ending with BLoC), data, testing and publishing, building a small app in each module.

In plain words

Flutter is a toolkit for building apps. You write your app once, in a language called Dart, and Flutter turns it into an Android app, an iPhone app, a website and a desktop program for Windows, macOS or Linux.

Think of Flutter as a painter who brings their own canvas and paint to every house. Other tools ask each house (Android, iOS, the browser) to lend them its furniture: its buttons, its lists, its text boxes. Flutter does not borrow. It paints every pixel itself. That is why a Flutter app looks the same on a cheap Android phone and on a new iPhone, unless you decide it should not.

You build the screen out of widgets. A widget is a small description of a piece of UI: “some text”, “a row of things”, “16 pixels of padding”, “a whole page with an app bar”. You nest widgets inside widgets, like boxes inside boxes, until you have a full screen.

Why it matters

Most companies need their app on Android and iOS, and often on the web too. Building each one separately means two or three teams, two or three codebases and bugs fixed two or three times. With Flutter, a small team ships one codebase to all of them. That is why agencies and start-ups like it: a single developer can deliver a client app for both stores.

For you as a developer, Flutter has three big benefits:

  • Speed of development. Hot reload shows your change in about a second without losing where you are in the app.
  • Full control of the design. Because Flutter paints everything, a custom design from a designer is not harder than a standard one.
  • Good performance. Release builds are compiled to native machine code, and the engine is built to draw smooth animations.

Flutter jobs usually ask for the same core skills this track teaches: Dart, layouts, state management (often BLoC or Provider), REST APIs, local storage, Firebase, testing and publishing to the stores.

How it works

To understand Flutter you need four ideas: its layers, the role of Dart, widgets as descriptions, and the trees Flutter keeps behind the scenes.

The layers

A Flutter app has three layers. You mostly work in the top one.

LayerWhat it doesWritten in
FrameworkWidgets, layout, Material Design components, animation, gestures. This is the code you import with package:flutter/material.dart.Dart
EngineDraws pixels (with the Impeller renderer on iOS and modern Android), lays out text, runs Dart, talks to the GPU.C++
EmbedderHosts the engine inside each platform: creates the window, passes touches and keyboard input, gives access to plugins.Kotlin/Java, Swift/Objective-C, C++ and others

Where Dart fits

Dart was designed for building user interfaces, and Flutter uses two of its tricks:

  • JIT (just-in-time) compilation in debug mode. The Dart VM can swap in changed code while the app runs. This is what powers hot reload.
  • AOT (ahead-of-time) compilation in release mode. Your code is compiled to native ARM or x64 machine code before it ships, so it starts fast and runs predictably. For the web, Dart compiles to JavaScript or WebAssembly.

Dart is also type-safe and null-safe, which catches many mistakes in the editor before you even run the app. Module 1 teaches Dart properly before you touch widgets.

Widgets and the declarative idea

In older UI toolkits you created a label, kept a reference to it, and later said “label, change your text”. Flutter is declarative: you write a build method that describes what the screen looks like for the current data. When the data changes, Flutter calls build again and compares the new description with the old one. It then updates only the parts of the screen that really changed.

A common way to say this is UI = f(state): the interface is a function of the state.

Here is a complete Flutter app. Read it from the top: main calls runApp with the root widget, MaterialApp sets up the theme, Scaffold gives a standard page with an app bar, and Center, Column, Icon and Text build the body.

Screen 1: Hello Flutter lib/main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(const HelloApp());
}

class HelloApp extends StatelessWidget {
  const HelloApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
      ),
      home: Scaffold(
        appBar: AppBar(title: const Text('Hello Flutter')),
        body: const Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.flutter_dash, size: 64),
              SizedBox(height: 12),
              Text('Everything here is a widget'),
            ],
          ),
        ),
      ),
    );
  }
}

A complete app: MaterialApp gives the theme, Scaffold gives the page, and Center, Column, Icon and Text are all widgets nested in a tree.

Notice three things you will see in every Flutter file:

  • StatelessWidget with a build(BuildContext context) method that returns widgets.
  • const in front of widgets that never change, which lets Flutter skip rebuilding them.
  • ColorScheme.fromSeed: you give one colour and Material 3 generates a full, matching palette.

Three trees (a first look)

Widgets are cheap, short-lived descriptions. Behind them Flutter keeps an element tree (which widget is mounted where, and which state belongs to it) and a render tree (objects that know their size and position and paint themselves). You write widgets; Flutter manages the other two. Lesson 2.1 goes deep on this.

Example: a tour of the course apps

Each module ends with a small app you can show in a portfolio. The first ones are console programs, so you can focus on Dart without any UI.

ModuleAppWhat it teaches
1 Dart in depthGrade Book, Library Manager, Weather Fetcher (console)Types, null safety, classes, async code
2 Flutter fundamentalsBusiness Card, counter and tip calculatorMaterialApp, Scaffold, stateless and stateful widgets
3 LayoutRecipe BookRows, columns, constraints, lists and grids
4 Material and themingTravel ExplorerMaterial 3 components, dark mode, custom widgets
5 Navigation and formsShop Catalog, Event RegistrationNavigator, go_router, validated forms
6 State managementShopping Cart (Provider), Task Tracker (BLoC)App state, Cubit, Bloc, testing blocs
7 Data and backendNews Reader, Notes, ChatHTTP and JSON, local storage, Firebase
8 Polish and shipOnboardingAnimations, tests, performance, publishing

Below is a small version of the Task Tracker. Switch between the two frames: tapping a checkbox changes the data in _tasks, setState asks Flutter to rebuild, and the “tasks left” text updates by itself. You never write “change that label”.

Screen 2: Task Tracker preview lib/main.dart

import 'package:flutter/material.dart';

void main() => runApp(const TaskApp());

class TaskApp extends StatelessWidget {
  const TaskApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Task Tracker',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
      ),
      home: const TaskScreen(),
    );
  }
}

class TaskScreen extends StatefulWidget {
  const TaskScreen({super.key});

  @override
  State<TaskScreen> createState() => _TaskScreenState();
}

class _TaskScreenState extends State<TaskScreen> {
  final _tasks = <String, bool>{
    'Buy groceries': true,
    'Finish Dart lesson': false,
    'Call the client': false,
  };

  @override
  Widget build(BuildContext context) {
    final left = _tasks.values.where((done) => !done).length;
    final label = left == 1 ? '1 task left' : '$left tasks left';
    return Scaffold(
      appBar: AppBar(title: const Text('My tasks')),
      body: ListView(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text(label,
                style: Theme.of(context).textTheme.titleMedium),
          ),
          for (final entry in _tasks.entries)
            CheckboxListTile(
              title: Text(entry.key),
              value: entry.value,
              onChanged: (value) {
                setState(() {
                  _tasks[entry.key] = value ?? false;
                });
              },
            ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
    );
  }
}

A small finished app. Tapping a checkbox calls setState, Flutter rebuilds the list and the “tasks left” count updates. You will rebuild this app properly with BLoC in module 6. States: Start → After one tap.

You do not need to understand every line yet. By the end of module 2 you will be able to write this from memory, and in module 6 you will rebuild it with BLoC, the architecture many production teams use.

Common mistakes

  • Thinking Flutter is a web view. It is not. Flutter apps are compiled and draw with their own engine; they do not run HTML inside the app.
  • Skipping Dart. Many beginners jump straight into widgets and then struggle with null safety, async code and classes. Learn the language first; widgets become much easier.
  • Judging performance in debug mode. Debug builds use JIT and extra checks, so they can feel slow. Measure speed with a profile or release build (flutter run --profile or --release).
  • Expecting native look automatically. Material widgets look like Material on iOS too. If a client wants an iOS look, use the Cupertino widgets or adaptive constructors on purpose.
  • Treating widgets like objects you edit. You do not keep a reference to a Text and change it. You change the data and rebuild.

Interview and real-world notes

  • “How is Flutter different from React Native?” A good short answer: React Native renders the platform’s own native components and runs JavaScript; Flutter paints its own widgets with its own engine and compiles Dart to native code. Avoid claiming one is always faster; say it depends on the app.
  • “Why Dart?” Mention JIT for hot reload in development, AOT for fast release builds, sound null safety, and a single language for UI and logic.
  • “What is a widget?” An immutable description of part of the UI. The framework compares widgets between builds and updates the element and render trees.
  • In client work, Flutter shines for custom-branded apps that must ship on Android and iOS together. For apps that are mostly heavy native features (for example deep system integrations), you may still write some platform code through plugins or platform channels, covered in module 8.
Remember: in Flutter you describe the screen for the current data. Change the data, and the framework rebuilds the screen for you.

Key terms

Flutter
Google’s open-source UI toolkit that builds apps for mobile, web and desktop from one Dart codebase.
Dart
The client-optimised, typed language Flutter apps are written in. It compiles ahead of time for release and just in time for development.
Widget
An immutable description of part of the UI, such as a Text, a Row or a whole screen.
Rendering engine
The part of Flutter that lays out and paints pixels on a canvas; Impeller is the default renderer on iOS and modern Android.
Hot reload
Injects changed code into the running app and rebuilds the UI in about a second while keeping the current state.
Declarative UI
You describe what the UI should look like for the current state; the framework works out how to update the screen.
TipIn interviews, explain that Flutter paints its own widgets instead of using native ones: that is why it looks consistent across platforms and why custom designs are cheap.
Hands-on lab7 steps · 3 exercise files
Quiz4 exam-style questions with explanations
Practice tests30 and 50-question mocks, scored out of 1000

The lab, quiz and practice tests for this lesson are for enrolled students, with progress saved to your own login.