"You don't need to be a Dart expert to build Flutter apps. But you do need to understand what you're reading. This guide gives you exactly that — no more, no less."

Dart is Google's programming language, designed in 2011 specifically to be easy to learn and fast to compile. If you know any C-family language (Java, C#, JavaScript, Kotlin), Dart will feel immediately familiar. If you're completely new to programming, Dart is one of the friendliest languages to start with.

Variables and Types

Dart is a statically typed language — every variable has a type. But Dart can also infer types automatically using var.

// Explicit type declaration
String name = 'Raushan';
int age = 32;
double salary = 85000.50;
bool isMCT = true;

// Type inference — Dart figures out the type from the value
var topicName = 'Flutter Getting Started';  // Dart infers: String
var lessonCount = 6;                          // Dart infers: int
var price = 0.0;                              // Dart infers: double

// Constants — value never changes
const pi = 3.14159;
final String city = 'Noida';  // final = set once, can't change after
📌 const vs final const means the value is known at compile time (like π). final means the value is set once at runtime and never changes after (like a user's name after login).

Null Safety — Dart's Most Important Feature

Dart has sound null safety — by default, variables cannot be null. This prevents the most common runtime crash in programming: the null pointer exception.

// This will NOT compile — String cannot be null by default
String name = null;  // ❌ Error

// To allow null, add ? after the type
String? name = null;  // ✅ This is fine — name can be null

// Null-aware operators
print(name?.length);     // Only calls .length if name is not null
print(name ?? 'Guest');  // If name is null, use 'Guest' instead

Functions

// Basic function
String greet(String name) {
  return 'Hello, $name!';
}

// String interpolation — use $ to embed variables
String fullGreeting(String name, String role) {
  return 'Hello, $name! You are a $role.';  // $ for variable, ${} for expression
}

// Arrow function — single expression, no need for {} and return
String greetShort(String name) => 'Hello, $name!';

// Optional parameters — use [] for positional, {} for named
void printTopic(String title, [int? lessons, bool? free]) {
  print('$title — ${lessons ?? 0} lessons — Free: ${free ?? false}');
}

// Named parameters — caller must use the name
void createUser({required String name, int age = 0}) {
  print('User: $name, Age: $age');
}

// Calling named parameters:
createUser(name: 'Raushan', age: 32);
createUser(name: 'Student');  // age defaults to 0

Lists, Maps and Sets

// List (like arrays in other languages)
List<String> topics = ['Flutter', 'Azure', 'Power BI'];
var numbers = [1, 2, 3, 4, 5];  // Dart infers List<int>

topics.add('Blazor');
topics.remove('Azure');
print(topics.length);     // 3
print(topics[0]);          // 'Flutter'
print(topics.contains('Power BI'));  // true

// Map (key-value pairs — like Dictionary in C# or Object in JS)
Map<String, int> examScores = {
  'PL-300': 750,
  'AZ-204': 820,
  'AZ-104': 780,
};
print(examScores['PL-300']);  // 750
examScores['AI-102'] = 800;   // Add new entry

// Iterating
for (var topic in topics) {
  print(topic);
}

examScores.forEach((exam, score) {
  print('$exam: $score');
});

Classes and Objects — OOP in Dart

Flutter is built entirely with classes. Everything you use in Flutter — Text, Button, Column — is a class. Understanding Dart classes is essential.

class Topic {
  // Properties
  String title;
  int lessonCount;
  bool isFree;

  // Constructor
  Topic(this.title, this.lessonCount, {this.isFree = false});

  // Named constructor
  Topic.free(String title) : this(title, 0, isFree: true);

  // Method
  String getSummary() {
    return '$title — $lessonCount lessons — ${isFree ? "Free" : "Paid"}';
  }
}

// Using the class
var flutter = Topic('Flutter Getting Started', 6, isFree: true);
print(flutter.getSummary());
// Output: Flutter Getting Started — 6 lessons — Free

// Inheritance
class PremiumTopic extends Topic {
  double price;

  PremiumTopic(String title, int lessons, this.price)
      : super(title, lessons, isFree: false);

  @override
  String getSummary() {
    return super.getSummary() + ' — ₹$price';
  }
}

Async / Await — Handling Asynchronous Code

Almost everything in a Flutter app that involves waiting — network requests, file reading, database queries — is asynchronous. Dart uses Future and async/await for this.

// A Future represents a value that will be available later
Future<String> fetchUserName() async {
  // Simulate a network request taking 2 seconds
  await Future.delayed(Duration(seconds: 2));
  return 'Raushan Ranjan';
}

// Calling an async function
void main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('User: $name');
  // Output after 2 seconds: User: Raushan Ranjan
}

// Real-world example — HTTP request pattern
Future<List<Topic>> loadTopics() async {
  try {
    final response = await http.get(Uri.parse('https://api.example.com/topics'));
    if (response.statusCode == 200) {
      // parse JSON and return List<Topic>
      return parseTopics(response.body);
    } else {
      throw Exception('Failed to load topics');
    }
  } catch (e) {
    print('Error: $e');
    return [];
  }
}
💡 Key Insight await can only be used inside an async function. Whenever you see await in Flutter code, you know it's waiting for something (usually network or disk I/O).

What You Will See in Flutter Code

Here is a minimal Flutter widget using everything above. Read it — you should understand all of it now:

import 'package:flutter/material.dart';

class TopicCard extends StatelessWidget {
  final String title;          // final property
  final int lessonCount;
  final bool isFree;

  // Named constructor with required and optional params
  const TopicCard({
    super.key,
    required this.title,
    required this.lessonCount,
    this.isFree = false,         // optional, defaults to false
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Text(title),                                     // String
            Text('$lessonCount lessons'),                    // interpolation
            Text(isFree ? 'Free' : 'Paid'),                 // ternary
          ],
        ),
      ),
    );
  }
}

Dart Quick Reference

  • Types: String, int, double, bool, List, Map — Dart infers with var
  • Null safety: Add ? to allow null — use ?? for fallback values
  • String interpolation: 'Hello $name' or '${expression}'
  • Functions: typed params, optional with [], named with {}, arrow with =>
  • Classes: constructor with this.property, inheritance with extends, override with @override
  • Async: Future<T> return type, async keyword on function, await to wait