Core Concepts in Flutter
Understanding the fundamental building blocks of Flutter applications
Introduction to Dart
Dart is the programming language used for Flutter development. It's a client-optimized language for fast apps on any platform. Before diving into Flutter, let's cover some Dart basics.
Variables and Data Types
Dart is a statically typed language, but it also supports type inference with the var keyword.
// Explicitly typed String name = 'John'; int age = 30; double height = 1.85; bool isStudent = true; // Type inference var country = 'USA'; // Dart infers this as String var population = 331000000; // Dart infers this as int // Constants final birthYear = 1990; // Cannot be reassigned const pi = 3.14159; // Compile-time constantFunctions
Functions in Dart are first-class objects, which means they can be assigned to variables and passed as arguments.
// Regular function void greet(String name) { print('Hello, \$name!'); } // Function with return value String getGreeting(String name) { return 'Hello, \$name!'; } // Arrow function (shorthand for single expressions) String greetPerson(String name) => 'Hello, \$name!'; // Optional parameters void introduce(String name, {int? age, String? occupation}) { print('Name: \$name'); if (age != null) print('Age: \$age'); if (occupation != null) print('Occupation: \$occupation'); } // Using the functions void main() { greet('Alice'); // Prints: Hello, Alice! print(getGreeting('Bob')); // Prints: Hello, Bob! introduce('Charlie', age: 25, occupation: 'Developer'); }Collections
Dart provides several collection types for organizing data.
// Lists (arrays) List<String> fruits = ['apple', 'banana', 'orange']; var numbers = [1, 2, 3, 4, 5]; // List<int> // Accessing elements print(fruits[0]); // Prints: apple // Adding elements fruits.add('grape'); // Maps (key-value pairs) Map<String, int> ages = { 'Alice': 30, 'Bob': 25, 'Charlie': 35, }; // Accessing values print(ages['Alice']); // Prints: 30 // Adding entries ages['David'] = 40;Flutter Widget Basics
In Flutter, everything is a widget. Widgets are the basic building blocks of a Flutter app's user interface.
Types of Widgets
There are two primary types of widgets in Flutter:
- StatelessWidget: A widget that doesn't maintain any state. Once built, it cannot change its appearance until it's rebuilt entirely.
- StatefulWidget: A widget that can maintain state and can rebuild itself when the state changes.
StatelessWidget Example
import 'package:flutter/material.dart'; class GreetingWidget extends StatelessWidget { final String name; // Constructor const GreetingWidget({Key? key, required this.name}) : super(key: key); @override Widget build(BuildContext context) { return Text('Hello, \$name!'); } } // Using the widget GreetingWidget(name: 'Flutter Developer')StatefulWidget Example
import 'package:flutter/material.dart'; class CounterWidget extends StatefulWidget { const CounterWidget({Key? key}) : super(key: key); @override _CounterWidgetState createState() => _CounterWidgetState(); } class _CounterWidgetState extends State<CounterWidget> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Count: \$_counter'), ElevatedButton( onPressed: _incrementCounter, child: Text('Increment'), ), ], ); } }The key difference is that StatefulWidget has a separate state class that can be updated with setState(), triggering a rebuild of the widget.
Layout Widgets
Flutter provides a rich set of layout widgets to help you arrange other widgets on the screen.
Container
A convenience widget that combines common painting, positioning, and sizing widgets.
Container( margin: EdgeInsets.all(10.0), padding: EdgeInsets.all(20.0), decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(10.0), ), child: Text( 'Hello, Flutter!', style: TextStyle(color: Colors.white), ), )Row and Column
Widgets that arrange their children in a horizontal (Row) or vertical (Column) array.
// Row example Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Icon(Icons.star), Icon(Icons.star), Icon(Icons.star), ], ) // Column example Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Title'), Text('Subtitle'), Text('Body text'), ], )Stack
A widget that positions its children relative to the edges of its box.
Stack( children: [ // Background image Image.asset('background.jpg'), // Overlay text Positioned( bottom: 20, right: 20, child: Text( 'Overlay Text', style: TextStyle(color: Colors.white), ), ), ], )Scaffold
A widget that implements the basic material design visual layout structure.
Scaffold( appBar: AppBar( title: Text('My Flutter App'), ), body: Center( child: Text('Hello, World!'), ), floatingActionButton: FloatingActionButton( onPressed: () {}, child: Icon(Icons.add), ), )User Input Widgets
Flutter provides various widgets for handling user input.
TextField
A widget that allows users to enter text.
TextField( decoration: InputDecoration( labelText: 'Username', hintText: 'Enter your username', border: OutlineInputBorder(), ), onChanged: (text) { print('Current text: \$text'); }, )Buttons
Flutter offers various button widgets for different use cases.
// Elevated Button (raised button with shadow) ElevatedButton( onPressed: () { print('Button pressed!'); }, child: Text('Press Me'), ) // Text Button (flat button without background) TextButton( onPressed: () { print('Text button pressed!'); }, child: Text('Text Button'), ) // Outlined Button (button with an outline) OutlinedButton( onPressed: () { print('Outlined button pressed!'); }, child: Text('Outlined Button'), )Checkbox and Switch
Widgets for boolean input.
// Checkbox example bool _isChecked = false; Checkbox( value: _isChecked, onChanged: (bool? value) { setState(() { _isChecked = value!; }); }, ) // Switch example bool _isSwitched = false; Switch( value: _isSwitched, onChanged: (bool value) { setState(() { _isSwitched = value; }); }, )Hot Reload
One of Flutter's most powerful features is Hot Reload, which allows you to see changes in your code almost instantly without losing the current state of your app.
How to Use Hot Reload
- Make changes to your Flutter code.
- Save the file (Ctrl+S or Cmd+S).
- If using an IDE like Android Studio or VS Code, the hot reload will happen automatically.
- If using the command line, press 'r' in the terminal where your app is running.
Hot Reload vs. Hot Restart
- Hot Reload: Preserves the state of your app but updates the UI based on code changes. It's faster but has limitations.
- Hot Restart: Restarts the app completely, losing all state but applying all code changes. Use this when hot reload doesn't work as expected.
To perform a hot restart, press 'R' (uppercase) in the terminal or use the hot restart button in your IDE.
Pro Tip
When designing Flutter UIs, think in terms of widget composition rather than inheritance. Flutter's design philosophy encourages composing small, single-purpose widgets to build complex UIs, rather than creating deep inheritance hierarchies.