DOCODIVE
Mobile Apps Free Learning Path Beginner

Mobile App Development — Beginner Guide

Learn Flutter from zero: Dart basics, widgets, layouts, input, navigation, and build your first real app.

6–8 weeks 20 lessons Flutter + Dart
01

What Is Mobile App Development?

15 min

Mobile app development is the process of creating software for smartphones and tablets. This lesson gives you the full picture before you write a single line of code.

What you'll learn

  • Understand what mobile app development really means
  • Learn the difference between mobile and web apps
  • Know the full development lifecycle

Concept

A mobile app is software built specifically for a phone or tablet operating system, mainly Android or iOS. Unlike websites, apps are installed on the device and can use hardware features like the camera, GPS, and sensors directly. Development involves designing the user interface, writing the app logic, and connecting to device features and remote services.

How it works

First you design what the user sees and how they navigate. Then you write the logic that responds to their actions. Finally you package the app into an installable file (APK for Android, IPA for iOS) and distribute it through app stores or directly.

Example

When you open Instagram, the feed, stories, and camera are all separate screens. The app logic fetches new posts, the UI displays them, and the camera hardware is accessed directly — this is mobile app development in action.

Understand it

The key idea is that a mobile app runs on the device itself, not inside a browser. This gives it direct access to hardware and offline capability, but it also means you must build separately for each platform or use a cross-platform tool.

⚠️ Common Mistake Assuming mobile apps are just 'websites in a smaller screen' — they are not. Native apps behave differently and access device hardware that websites often cannot.
💡 Pro Tip Before coding, always clarify: which platform, what core features, and who is the user?
✅ Key takeaway: Mobile app = UI + logic + device features, running on the phone itself.
Flutter architectural overview

Practice

List three apps you use daily and note one hardware feature each one uses.

Think about camera, GPS, notifications, biometrics, or offline storage.
✓ Example: Google Maps uses GPS, WhatsApp uses camera + notifications, Spotify uses offline storage.
01 / 20 Next
02

Native vs Cross-Platform Development

15 min

There are two main ways to build mobile apps: native (one platform at a time) or cross-platform (both from one codebase). Choosing wisely saves months of work.

What you'll learn

  • Understand native development
  • Understand cross-platform development
  • Compare the trade-offs of both approaches

Concept

Native development means building separately for Android (Kotlin/Java) and iOS (Swift). Cross-platform tools like Flutter and React Native let you write one codebase in Dart or JavaScript and compile it for both platforms. Cross-platform is usually faster and cheaper, while native gives the highest performance and most direct platform access.

How it works

A cross-platform framework provides its own rendering engine and widgets. Flutter, for example, draws every pixel itself using Skia, so the same UI looks identical on Android and iOS without relying on native components.

Example

A startup building a minimum viable product often chooses Flutter to ship on both stores with one team. A large company with a huge budget may keep separate native teams for the smoothest possible experience.

Understand it

Cross-platform does not mean lower quality — modern tools like Flutter are extremely fast. The real difference is in edge cases, very platform-specific features, and large-team flexibility.

⚠️ Common Mistake Believing cross-platform apps are always slower or worse. In practice, Flutter apps perform close to native for most use cases.
💡 Pro Tip Your language preference matters: choose Flutter for Dart, React Native for JavaScript.
✅ Key takeaway: There is no single best option — only the best fit for your team and goal.
Flutter FAQ — why Flutter

Practice

For a simple to-do app built by a solo beginner, which approach would you choose and why?

Think about cost, time, and whether you need deep platform-specific features.
✓ Cross-platform (Flutter) — one codebase, faster to ship, and a to-do app does not need deep native features.
Previous 02 / 20 Next
03

Why Flutter?

15 min

Flutter is Google's open-source framework for building beautiful, fast mobile apps from a single codebase. This lesson explains why it has become so popular.

What you'll learn

  • Learn Flutter's key strengths
  • Understand the Dart language connection
  • Know what kinds of apps Flutter suits best

Concept

Flutter uses the Dart language and compiles directly to native machine code, giving high performance without a JavaScript bridge. Its biggest strength is a rich set of pre-built widgets that make beautiful UIs easy to build, plus hot reload that lets you see changes instantly while coding.

How it works

You write Dart code that describes widgets. Flutter's engine renders those widgets directly on screen using Skia, so there is no lag from translating between JavaScript and native code.

Example

flutter create my_app creates a complete project. You edit lib/main.dart, press 'r' for hot reload, and changes appear on the emulator in under a second.

Understand it

Hot reload is the killer feature — it keeps you in the flow because you see results immediately instead of waiting for a full rebuild each time.

⚠️ Common Mistake Skipping Dart fundamentals and jumping straight into widgets. Without basic Dart knowledge, Flutter code will feel confusing.
💡 Pro Tip Learn Dart basics first (variables, functions, classes) — it makes Flutter much easier.
✅ Key takeaway: Flutter = fast development + beautiful UI + one codebase for both platforms.
Why Flutter — official

Practice

Name two features of Flutter that make it good for beginners.

Think about feedback speed and UI building blocks.
✓ Hot reload (instant feedback) and pre-built Material widgets (no need to style everything from scratch).
Previous 03 / 20 Next
04

Installing Flutter & Setting Up the Environment

25 min

Before writing code, you need the Flutter SDK, an editor, and an emulator or real device. This lesson walks through the setup step by step.

What you'll learn

  • Install the Flutter SDK
  • Set up an editor (VS Code or Android Studio)
  • Run flutter doctor to verify the setup

Concept

Flutter provides a single SDK that includes the framework, Dart, and tools for building and testing. You also need a code editor and either an Android emulator, iOS simulator, or a physical device to run your app.

How it works

Download the Flutter SDK for your operating system and add it to your PATH. Then install Android Studio (for the Android emulator) or Xcode (for iOS on Mac). Finally run 'flutter doctor' — it checks every dependency and tells you exactly what is missing.

Example

On Windows, you install Android Studio, create an Android Virtual Device (AVD), then run 'flutter emulators' and 'flutter run' to launch your first app.

Understand it

flutter doctor is your safety net. If anything is missing or misconfigured, it tells you the exact fix — never skip this step.

⚠️ Common Mistake Ignoring the flutter doctor warnings and wondering why the app will not build.
💡 Pro Tip Use VS Code with the Flutter extension for the lightest setup; Android Studio only if you prefer it.
✅ Key takeaway: SDK + editor + emulator, then run flutter doctor and fix every warning.
Install Flutter — official guide

Practice

Run 'flutter doctor' and list any issues it reports.

Look for the checkmarks and warning symbols in the output.
✓ A clean setup shows green checkmarks for Flutter, Android toolchain, and your editor.
Previous 04 / 20 Next
05

Flutter Project Structure

20 min

A Flutter project is more than just code — it has a specific folder layout that keeps platform files, assets, and your Dart code organised.

What you'll learn

  • Understand the key folders in a Flutter project
  • Know what lib/main.dart is for
  • Learn what pubspec.yaml controls

Concept

The most important folder is lib/, where all your Dart code lives. main.dart is the entry point. The pubspec.yaml file declares your app's dependencies, assets, and metadata. The android/ and ios/ folders contain platform-specific configuration that Flutter manages for you.

How it works

When you run 'flutter create', it generates the full structure. You spend almost all your time inside lib/ and pubspec.yaml. The platform folders are usually left alone unless you add native plugins or custom settings.

Example

A new project's lib/main.dart contains the default counter app — a complete, runnable Flutter app in about 90 lines that you will gradually replace with your own code.

Understand it

You do not need to understand android/ and ios/ internals as a beginner. Focus on lib/ for code and pubspec.yaml for dependencies.

⚠️ Common Mistake Editing android/ or ios/ files manually before understanding what they do.
💡 Pro Tip Always run 'flutter pub get' after changing pubspec.yaml to fetch new dependencies.
✅ Key takeaway: lib/ is your code, pubspec.yaml is your project manifest — the rest is mostly managed.
Flutter codelab — project overview

Practice

Create a new Flutter project and identify the three most important files or folders.

Think: entry point, dependencies, and code location.
✓ lib/main.dart (entry point), pubspec.yaml (dependencies/assets), lib/ (all Dart code).
Previous 05 / 20 Next
06

Your First Flutter App

25 min

Time to write real code. This lesson replaces the default counter app with a simple, friendly welcome screen.

What you'll learn

  • Understand the basic structure of a Flutter app
  • Create a simple screen with text
  • Run the app and see the result

Concept

Every Flutter app starts in the main() function, which calls runApp(). The runApp() function takes a root widget — usually a MaterialApp — and displays it. MaterialApp provides Material Design styling and a home screen.

How it works

main() launches the app. runApp(MyApp()) tells Flutter 'this is the root widget'. MyApp returns MaterialApp, and home points to a Scaffold, which gives you a basic page with a body.

Example

import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('My First App')), body: const Center(child: Text('Hello, Flutter!')), ), ); } }

Understand it

runApp() takes your top widget. MaterialApp gives Material theming. Scaffold is the page skeleton. Center places the Text in the middle of the screen.

⚠️ Common Mistake Forgetting to import 'package:flutter/material.dart', which provides MaterialApp, Scaffold, and Text.
💡 Pro Tip Type 'stless' in VS Code and press Tab to auto-generate a StatelessWidget template.
✅ Key takeaway: main() → runApp() → MaterialApp → Scaffold → widgets you can see.
Write your first Flutter app

Practice

Change the default app's title and body text to your own name.

Edit the AppBar title and the Center child Text.
✓ Replace the strings with your name and run 'flutter run' to see it.
Previous 06 / 20 Next
07

Dart Basics for Flutter

20 min

Dart is the language behind Flutter. This lesson introduces the essential syntax you will use in every single Flutter file.

What you'll learn

  • Understand Dart's role in Flutter
  • Learn basic syntax and structure
  • Know the most common Dart concepts

Concept

Dart is an object-oriented, statically typed language that is easy to learn if you have used JavaScript, Java, or Python. In Flutter you will constantly write classes, functions, and expressions in Dart. Everything in Flutter — even a button or a text label — is an object.

How it works

A Dart file starts with imports, then defines functions and classes. Statements end with semicolons. Types are declared before variable names, like 'int count = 0;'.

Example

void greet(String name) { print('Hello, $name!'); } void main() { greet('Flutter'); }

Understand it

The dollar sign inside a string ('$name') is string interpolation — it inserts the variable value directly into the text.

⚠️ Common Mistake Forgetting semicolons at the end of statements — Dart requires them.
💡 Pro Tip Dart is strongly typed, but 'var' and 'final' let you infer the type and keep code shorter.
✅ Key takeaway: Dart is the language; Flutter is the framework built on top of it.
Dart language tour

Practice

Write a Dart function that takes a number and prints 'The number is X'.

Use a parameter and string interpolation.
✓ void showNumber(int n) { print('The number is $n'); }
Previous 07 / 20 Next
08

Variables, Data Types & Operators

20 min

Every program stores and manipulates data. This lesson covers Dart's core data types and the operators you will use constantly.

What you'll learn

  • Learn Dart's basic data types
  • Understand variable declaration
  • Use arithmetic and comparison operators

Concept

Dart has numbers (int, double), strings (String), booleans (bool), lists (List), and maps (Map). Variables can be declared with an explicit type, or with 'var' and 'final' for type inference and immutability.

How it works

'int age = 20;' declares an integer. 'final name = 'Ali';' creates an unchangeable string. Operators like +, -, *, / do math, and ==, !=, >, < compare values.

Example

int a = 10; int b = 3; int sum = a + b; // 13 double result = a / b; // 3.333... bool isGreater = a > b; // true String label = 'Sum is $sum';

Understand it

int division '/' always returns a double in Dart. Use '~/' for integer division if you need a whole number result.

⚠️ Common Mistake Using 'final' and then trying to reassign the variable later — final values cannot change.
💡 Pro Tip Prefer 'final' over 'var' by default; it makes your intent clearer and prevents accidental changes.
✅ Key takeaway: Types + variables + operators = the foundation of all Dart logic.
Dart variables

Practice

Create two numbers, add them, and print whether the result is greater than 20.

Use int, +, and a comparison.
✓ int x = 12; int y = 15; int total = x + y; print(total > 20); // true
Previous 08 / 20 Next
09

Conditions & Loops

20 min

Apps make decisions and repeat actions. This lesson teaches Dart's if/else conditions and for/while loops.

What you'll learn

  • Use if/else for decisions
  • Use for and while loops
  • Understand when to use each loop type

Concept

Conditions let code choose different paths — if a user is logged in, show their profile; otherwise show a login button. Loops repeat code — a for loop iterates a known number of times, while a while loop repeats until a condition becomes false.

How it works

'if (condition) { ... } else { ... }' branches the code. 'for (var i = 0; i < 5; i++)' runs five times. 'while (condition)' keeps running until the condition is false.

Example

for (var i = 1; i <= 5; i++) { if (i % 2 == 0) { print('$i is even'); } else { print('$i is odd'); } }

Understand it

The modulo operator '%' gives the remainder after division. i % 2 == 0 means the number is even.

⚠️ Common Mistake Creating an infinite loop with while(true) and no break — the app will hang.
💡 Pro Tip Use for loops when you know the count; use while when you are waiting for a condition to change.
✅ Key takeaway: if/else decides, loops repeat — together they control the flow of your app.
Dart loops

Practice

Print numbers from 1 to 10, but for multiples of 3 print 'Fizz' instead.

Use a for loop and if with the modulo operator.
✓ for (var i = 1; i <= 10; i++) { if (i % 3 == 0) { print('Fizz'); } else { print(i); } }
Previous 09 / 20 Next
10

Functions & Parameters

20 min

Functions are reusable blocks of code. In Flutter, almost everything you build is expressed as a function or a widget build method.

What you'll learn

  • Define and call functions
  • Use parameters and return values
  • Understand named and optional parameters

Concept

A function takes inputs (parameters), does work, and optionally returns a result. Dart supports positional parameters, named parameters, and default values. This flexibility appears everywhere in Flutter widget constructors.

How it works

'int add(int a, int b) => a + b;' is a shorthand function that returns the sum. Named parameters use curly braces: 'void greet({required String name}) { ... }'.

Example

String describe({required String name, int age = 20}) { return '$name is $age years old'; } // Call it: describe(name: 'Ali'); // 'Ali is 20 years old' describe(name: 'Sara', age: 25); // 'Sara is 25 years old'

Understand it

Named parameters with 'required' must be provided; those with a default value are optional. This is how Flutter widgets take dozens of optional settings.

⚠️ Common Mistake Forgetting 'required' on a named parameter that must be passed, then wondering why the call fails.
💡 Pro Tip Use the arrow syntax '=>' for simple one-expression functions — it reads more cleanly.
✅ Key takeaway: Functions package logic; Flutter widgets are built by functions returning UI.
Dart functions

Practice

Write a function that takes a first and last name and returns the full name.

Use two parameters and string interpolation.
✓ String fullName(String first, String last) { return '$first $last'; }
Previous 10 / 20 Next
11

Understanding Widgets

20 min

In Flutter, everything is a widget. This is the single most important idea in the entire framework, and this lesson explains what it means.

What you'll learn

  • Understand the widget concept
  • Learn how widgets compose into a UI
  • Know that widgets are immutable

Concept

A widget is a description of what part of the UI should look like. Text, Button, Row, Column, and even the whole app are widgets. You build a screen by nesting widgets inside each other to form a widget tree.

How it works

Each widget has a build() method that returns another widget. The root MaterialApp builds a Scaffold, which builds a Column, which builds Text widgets — a tree from root to leaf.

Example

Column( children: [ Text('Hello'), Text('World'), Icon(Icons.star), ], )

Understand it

The Column widget is the parent; the Text and Icon widgets are its children. Flutter renders the tree from top to bottom.

⚠️ Common Mistake Thinking of widgets as the final rendered pixels. They are descriptions — Flutter turns them into pixels each frame.
💡 Pro Tip Read code from the outside in: the top widget is the container, inner widgets are its content.
✅ Key takeaway: Everything is a widget — you build UIs by composing widgets into a tree.
Introduction to widgets

Practice

Name five widgets you have already seen in the lessons so far.

Think about text, layout, and interaction.
✓ Text, Column, Row, Container, Icon, AppBar, Scaffold, MaterialApp.
Previous 11 / 20 Next
12

Stateless vs Stateful Widgets

25 min

There are two kinds of widgets in Flutter: stateless and stateful. Knowing the difference is essential to building responsive apps.

What you'll learn

  • Understand stateless widgets
  • Understand stateful widgets
  • Know when to use each

Concept

A stateless widget never changes after it is built — a static label or icon is a good example. A stateful widget can change over time — a counter or a form input needs state because the UI must update when the data changes.

How it works

A stateless widget only has a build() method. A stateful widget has two parts: the widget itself and a State object that holds mutable data. Calling setState() tells Flutter to rebuild that widget with new data.

Example

StatelessWidget: class Greeting extends StatelessWidget { const Greeting({super.key}); @override Widget build(BuildContext context) => const Text('Hello'); }

Understand it

Stateless widgets are simpler and faster. Use them unless the widget's own data changes; in that case use a stateful widget.

⚠️ Common Mistake Marking a widget as stateful when it could be stateless — this adds unnecessary complexity.
💡 Pro Tip Start with stateless; change to stateful only when you need setState.
✅ Key takeaway: Stateless = fixed UI. Stateful = UI that updates with setState().
Adding interactivity to Flutter

Practice

Decide whether a profile picture and a like button should be stateless or stateful.

Does it change after being built?
✓ Profile picture is stateless (fixed); like button is stateful (toggles liked/unliked).
Previous 12 / 20 Next
13

Text, Icons, Images & Buttons

25 min

These are the building blocks of almost every screen. This lesson teaches Flutter's most common visible widgets.

What you'll learn

  • Display text with styling
  • Use icons and images
  • Create buttons that respond to taps

Concept

Text shows a string with optional style. Icon displays a Material icon. Image loads graphics from assets or the network. Buttons like ElevatedButton, TextButton, and IconButton trigger actions when pressed.

How it works

Each widget takes parameters: Text takes a string and style, Icon takes an IconData, Image.asset/network loads images, and buttons take a child and an onPressed callback.

Example

Column( children: [ Text('Welcome', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), const Icon(Icons.favorite, color: Colors.red), ElevatedButton( onPressed: () => print('Pressed!'), child: const Text('Tap me'), ), ], )

Understand it

The onPressed callback runs when the button is tapped. If onPressed is null, the button is disabled.

⚠️ Common Mistake Forgetting onPressed on a button — it renders but does nothing when tapped.
💡 Pro Tip Use const before widgets like Text and Icon for better performance; Flutter skips rebuilding them.
✅ Key takeaway: Text, Icon, Image, and buttons are the visible vocabulary of Flutter.
Basic Flutter widgets

Practice

Build a screen with a title, an icon, and a button that prints a message.

Use a Column inside a Scaffold body.
✓ Scaffold(body: Center(child: Column(children: [Text('Hi'), Icon(Icons.star), ElevatedButton(onPressed: () => print('clicked'), child: Text('Go'))])))
Previous 13 / 20 Next
14

Rows, Columns & Containers

25 min

Layout is how you arrange widgets on screen. Rows, Columns, and Containers are the three most important layout tools.

What you'll learn

  • Arrange widgets horizontally with Row
  • Arrange widgets vertically with Column
  • Use Container for size, padding, and decoration

Concept

Row places children side by side. Column stacks children top to bottom. Container wraps a single child and adds padding, margin, size, color, and border. Combining these three lets you build almost any screen.

How it works

Row and Column take a children list. Container takes one child and styling properties. Nesting them creates complex layouts — a Column of Rows is the classic grid-like pattern.

Example

Container( padding: const EdgeInsets.all(16), color: Colors.blue[100], child: Column( children: [ Text('First'), SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text('A'), Text('B')], ), ], ), )

Understand it

SizedBox creates fixed spacing. mainAxisAlignment controls how children are distributed along the main axis (horizontal for Row, vertical for Column).

⚠️ Common Mistake Putting too many children in a Row without wrapping — it overflows on small screens.
💡 Pro Tip Use SizedBox for simple spacing; use mainAxisAlignment to distribute leftover space.
✅ Key takeaway: Row = horizontal, Column = vertical, Container = styled box.
Flutter layout guide

Practice

Create a screen with two texts side by side and one text below them.

Use a Column containing a Row, then another Text.
✓ Column(children: [Row(children: [Text('A'), Text('B')]), Text('C')])
Previous 14 / 20 Next
15

Padding, Margin & Alignment

20 min

Whitespace and positioning make a UI feel polished. This lesson covers Flutter's spacing and alignment tools.

What you'll learn

  • Add padding inside a widget
  • Add margin around a widget
  • Align and center content precisely

Concept

Padding is space inside a widget's border; margin is space outside it. Container accepts both padding and margin. Alignment controls where a child sits inside its parent — Center places it in the middle, Align lets you pick any corner or edge.

How it works

EdgeInsets.all(16) gives equal space on all sides; EdgeInsets.symmetric adds different vertical/horizontal values. Alignment values like topLeft, center, and bottomRight position a child within available space.

Example

Container( margin: const EdgeInsets.all(20), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), child: const Align( alignment: Alignment.topRight, child: Text('Top right'), ), )

Understand it

Margin pushes the container away from siblings; padding pushes the child away from the container edges; Align controls the child's position in remaining space.

⚠️ Common Mistake Confusing padding with margin — padding affects the inside, margin the outside.
💡 Pro Tip Wrap with Padding widget when you only need spacing and no box styling.
✅ Key takeaway: Padding = inside, margin = outside, alignment = position.
Flutter padding docs

Practice

Center a box with 30px margin and 15px padding containing the text 'Hello'.

Use Container with margin, padding, and a Center child.
✓ Container(margin: EdgeInsets.all(30), padding: EdgeInsets.all(15), child: Center(child: Text('Hello')))
Previous 15 / 20 Next
16

Lists & ListView

25 min

Almost every app shows a list of items — messages, posts, products. ListView is Flutter's scrollable list widget.

What you'll learn

  • Understand List basics in Dart
  • Build scrollable lists with ListView
  • Render lists dynamically with ListView.builder

Concept

A Dart List holds an ordered collection of values. ListView renders a scrollable list of widgets. For small fixed lists you can pass children directly; for long or dynamic lists, ListView.builder creates items on demand, which is much more efficient.

How it works

ListView(children: [...]) builds everything at once. ListView.builder(itemCount: n, itemBuilder: (context, i) => ...) lazily builds only the visible items as you scroll.

Example

final names = ['Ali', 'Sara', 'Omar']; ListView.builder( itemCount: names.length, itemBuilder: (context, index) { return ListTile(title: Text(names[index])); }, )

Understand it

The itemBuilder receives an index and returns a widget for that position. Only visible items are built, so a list of 10,000 items stays fast.

⚠️ Common Mistake Using ListView(children: [...]) for very long lists — it builds every item and can lag.
💡 Pro Tip Always use ListView.builder for dynamic or long lists; use children only for tiny static lists.
✅ Key takeaway: List holds data, ListView displays it, builder makes it efficient.
Flutter lists

Practice

Render a ListView with five items, each showing 'Item 1' through 'Item 5'.

Use ListView.builder with itemCount 5 and index + 1.
✓ ListView.builder(itemCount: 5, itemBuilder: (c, i) => ListTile(title: Text('Item ${i + 1}')))
Previous 16 / 20 Next
17

User Input & Text Fields

25 min

Users give input through text fields, switches, and sliders. This lesson focuses on the most common one — TextField.

What you'll learn

  • Collect text input with TextField
  • Use a controller to read input
  • Handle form input correctly

Concept

TextField lets users type text. A TextEditingController holds the current value. You attach the controller to the field, then read controller.text whenever you need the input. TextField also has onChanged, which fires every time the text changes.

How it works

Create a controller, pass it to the TextField, and read controller.text in a button's onPressed. Don't forget to dispose the controller to free resources.

Example

final controller = TextEditingController(); TextField( controller: controller, decoration: const InputDecoration( hintText: 'Enter your name', border: OutlineInputBorder(), ), ), ElevatedButton( onPressed: () => print(controller.text), child: const Text('Submit'), ),

Understand it

The controller is the bridge between the UI and your logic. Reading controller.text gives the latest value without needing to track every keystroke.

⚠️ Common Mistake Forgetting to call controller.dispose() in the State's dispose method — this leaks memory.
💡 Pro Tip Use TextField's onChanged when you need live updates, controller when you only need the final value.
✅ Key takeaway: TextField captures input; TextEditingController gives you access to it.
Flutter text widgets

Practice

Create a text field and a button; when the button is pressed, print the text field's contents.

Use a TextEditingController and read .text in onPressed.
✓ final c = TextEditingController(); // in State TextField(controller: c), ElevatedButton(onPressed: () => print(c.text), child: Text('Print'))
Previous 17 / 20 Next
18

Navigation Between Screens

25 min

Real apps have multiple screens. This lesson teaches how to move between them and pass data along.

What you'll learn

  • Push a new screen
  • Pop back to the previous screen
  • Pass data between screens

Concept

Flutter uses a Navigator to manage a stack of screens. Navigator.push() adds a new screen on top; Navigator.pop() removes it and returns to the previous one. You can pass data to the new screen through its constructor.

How it works

Define a route with MaterialPageRoute that builds the next screen. Call Navigator.push(context, MaterialPageRoute(builder: (context) => SecondScreen())) to open it, and Navigator.pop(context) to go back.

Example

// From first screen Navigator.push( context, MaterialPageRoute(builder: (context) => const SecondScreen(name: 'Ali')), ); // SecondScreen constructor class SecondScreen extends StatelessWidget { final String name; const SecondScreen({super.key, required this.name}); @override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: Text('Hello, $name')), ); }

Understand it

push adds a screen to the stack; pop removes it. The constructor parameter 'name' is how you pass data to the next screen.

⚠️ Common Mistake Passing data through global variables instead of constructors — this creates messy, hard-to-track state.
💡 Pro Tip Use named routes for larger apps; use MaterialPageRoute directly while learning.
✅ Key takeaway: Navigator.push opens a screen, pop closes it, constructors pass data.
Flutter navigation

Practice

Create two screens; a button on the first opens the second, and the second has a back button.

Use AppBar's automatic back button or Navigator.pop.
✓ Navigator.push for opening, and AppBar automatically shows a back button when pushed.
Previous 18 / 20 Next
19

Basic State & UI Updates

25 min

Now we bring it together: state that changes the UI. This lesson explains setState, the simplest way to update a screen.

What you'll learn

  • Understand state in Flutter
  • Update UI with setState
  • Build a simple interactive counter

Concept

State is any data that can change and affect the UI. In a StatefulWidget, you store state in the State object and call setState() to rebuild the UI when that data changes. setState tells Flutter 'the data changed, redraw the screen'.

How it works

Declare a mutable variable in the State class. In a button's onPressed, update the variable and wrap the change in setState(() { ... }). Flutter then rebuilds the widget with the new value.

Example

int _count = 0; ElevatedButton( onPressed: () { setState(() { _count = _count + 1; }); }, child: Text('Count: $_count'), )

Understand it

Without setState, the variable changes but the UI does not redraw. setState is the signal that triggers the rebuild.

⚠️ Common Mistake Updating a variable outside setState and expecting the UI to change — it will not.
💡 Pro Tip Keep setState calls small and only for the specific change; it is efficient enough for simple apps.
✅ Key takeaway: State + setState = interactive UI that responds to the user.
Flutter interactivity

Practice

Add a second button that decreases the counter, but never lets it go below zero.

Use an if condition inside setState.
✓ onPressed: () { setState(() { if (_count > 0) _count--; }); }
Previous 19 / 20 Next
20

Mini Project — To-Do / Counter App

40 min

Time to combine everything. This final lesson guides you through building a simple, complete app with input, lists, state, and navigation.

What you'll learn

  • Combine widgets, state, and input
  • Build a functional to-do list
  • Understand the complete app structure

Concept

A to-do app needs: a text field to type tasks, a button to add them, a list to display them, and state to hold the tasks. This ties together TextField, ListView, setState, and basic layout — everything from the previous nineteen lessons.

How it works

Maintain a List<String> of tasks in the State. On button press, read the text field, add the task to the list, clear the field, and call setState. Render the list with ListView.builder. Optionally add a delete button to each row.

Example

final _tasks = <String>[]; final _controller = TextEditingController(); void _addTask() { final text = _controller.text.trim(); if (text.isEmpty) return; setState(() => _tasks.add(text)); _controller.clear(); } // UI: Column with TextField, button, and Expanded(ListView.builder(...))

Understand it

The list holds data, setState refreshes it, ListView.builder renders it, and the controller reads input. Each piece maps to a lesson you have already learned.

⚠️ Common Mistake Forgetting to clear the text field after adding a task, so the same task appears twice or the field stays filled.
💡 Pro Tip Trim input before storing to avoid empty or whitespace-only tasks.
✅ Key takeaway: A real app = state + input + list + layout, working together.
Build a Flutter app codelab

Practice

Extend the to-do app by adding a delete icon next to each task.

Use ListTile with a trailing IconButton that removes from the list inside setState.
✓ ListTile( title: Text(_tasks[i]), trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () => setState(() => _tasks.removeAt(i)), ), )
Previous 20 / 20
You have completed all 20 beginner lessons.

Move on to Intermediate for APIs, state management, and real-world apps.

Continue to Intermediate

📱 Scan this QR code with your phone camera to instantly open this page.

Works on iOS, Android, and any modern device. No app installation required.

Account Verified!

Your email has been verified successfully.