- Flutter Development Tutorial (Beginner to Intermediate)
- Part 1: Introduction to Flutter and Environment Setup
- Part 2: Dart Basics for Flutter
- Part 3: Understanding Widgets and Building UI
- Part 4: Navigation and Routing
- Part 5: Working with Forms and Input Handling
- Part 6: Lists, Grids, and Dynamic Content
- Part 7: Advanced State Management
4. Introduction to Dart Programming (Deeper Dive)
Variables, Data Types, and Keywords
var: Can be reassigned, but Dart infers the type based on the initial value.
var name = 'John'; // Dart infers this as a String.
name = 'Doe'; // Valid because var allows reassignment.
final: Cannot be reassigned after initialization but is not a compile-time constant.
dart.
final age = 25;
// age = 26; // This will throw an error.
const: Like final, but it must be a compile-time constant (i.e., known when the program starts).
const pi = 3.14;
// pi = 3.1415; // Compile-time error
Note: Always use const for values that never change and should be evaluated at compile-time for optimization.
Nullable vs. Non-nullable Variables (Dart 2.12+)
By default, variables in Dart are non-nullable. You must explicitly allow them to be nullable by adding ?.
String? nullableName; // Can be null
nullableName = null; // Valid
String nonNullableName = 'John';
// nonNullableName = null; // Error: null is not allowed
Collections (List, Set, Map)
- List: A list is an ordered collection of items. It can be fixed-length or growable.
List<int> numbers = [1, 2, 3];
numbers.add(4); // Growable list allows adding elements
- Set: A Set is an unordered collection of unique items.
Set<String> uniqueNames = {'John', 'Jane', 'John'}; // Only {'John', 'Jane'}
- Map: A Map is a collection of key-value pairs.
Map<String, String> capitals = {
'USA': 'Washington, D.C.',
'France': 'Paris',
};
Higher-order Functions
Functions can be passed as arguments, returned by other functions, and assigned to variables.
void execute(Function action) {
action();
}
void sayHello() {
print('Hello!');
}
void main() {
execute(sayHello); // Pass function as argument
}
5. Understanding the main() Function and App Structure (Deeper Dive)
The main() Function
The main() function is the entry point of every Dart and Flutter app. Let’s break down its components:
- main(): Starts your app. You can perform any initialization here.
- runApp(): Instructs Flutter to display the provided widget (usually a MaterialApp or CupertinoApp).
- MyApp class: A custom widget, often a stateless widget at the root of your app.
void main() {
runApp(MyApp()); // Starts the Flutter app by running MyApp
}
The Widget Tree
Flutter builds a widget tree where every visual element (button, text, image) is a widget. The root widget is passed to runApp().
Let’s take a more detailed look at a typical app:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('App Title'),
),
body: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('Hello, Flutter!'),
);
}
}
- MaterialApp: The app shell that provides navigation and themes.
- Scaffold: Provides basic structure like AppBar, Body, and FloatingActionButton.
- MyHomePage: Custom widget containing the app’s content.