Back to Mobile Development

Module 4: Flutter & Dart

Build beautiful, natively compiled applications with Flutter and Dart programming language.

What is Flutter?

Flutter is Google's UI toolkit for building natively compiled applications from a single codebase. Think of it as a complete framework that includes everything you need - UI widgets, rendering engine, testing tools, and more. Unlike React Native which uses native components, Flutter draws its own UI.

🚀 Why Flutter?

  • Fast Development: Hot reload in milliseconds
  • Beautiful UI: Material Design & Cupertino widgets
  • Native Performance: Compiled to ARM code
  • Single Codebase: iOS, Android, Web, Desktop
  • Growing Ecosystem: 30,000+ packages on pub.dev
  • Backed by Google: Used in Google Pay, Alibaba

Dart Programming Language

Dart is the language behind Flutter. It's easy to learn, especially if you know JavaScript or Java.

Dart Basics:

// Variables

var name = 'Flutter'; // Type inferred

String title = 'Developer'; // Explicit type

int age = 25;

double price = 99.99;

bool isActive = true;

// Null safety (Dart 2.12+)

String? nullableName; // Can be null

String nonNullName = 'John'; // Cannot be null

// Functions

int add(int a, int b) {

return a + b;

}

// Arrow functions

int multiply(int a, int b) => a * b;

// Classes

class Person {

String name;

int age;

Person(this.name, this.age);

void greet() {

print('Hi, I am $name');

}

}

Dart Features:

  • • Sound Null Safety: Prevents null errors at compile time
  • • Async/Await: Easy asynchronous programming
  • • Collections: List, Set, Map with powerful methods
  • • Mixins: Reuse code across multiple classes
  • • Extension Methods: Add methods to existing classes

Flutter Widgets

Everything in Flutter is a widget! Widgets are the building blocks of your UI.

Stateless Widget

Immutable, doesn't change over time

class MyWidget extends

StatelessWidget {

@override

Widget build(BuildContext context) {

return Text('Hello');

}

}

Stateful Widget

Can change state and rebuild

class Counter extends

StatefulWidget {

@override

_CounterState createState() =>

_CounterState();

}

Common Widgets:

// Layout Widgets

Container() // Box with padding, margin, decoration

Row() // Horizontal layout

Column() // Vertical layout

Stack() // Overlapping widgets

Padding() // Add padding

// UI Widgets

Text('Hello') // Display text

Image.network(url) // Display image

Icon(Icons.home) // Material icon

ElevatedButton() // Material button

TextField() // Text input

// Scrolling

ListView() // Scrollable list

GridView() // Grid layout

SingleChildScrollView() // Scrollable single child

Your First Flutter App

import 'package:flutter/material.dart';

void main() {

runApp(MyApp());

}

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

title: 'Flutter Demo',

theme: ThemeData(

primarySwatch: Colors.blue,

),

home: HomePage(),

);

}

}

class HomePage extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('My First App'),

),

body: Center(

child: Text(

'Hello, Flutter!',

style: TextStyle(fontSize: 24),

),

),

);

}

}

State Management

Managing state is crucial in Flutter apps. Here are the popular approaches:

setState (Built-in)

Simple state management for single widgets.

class Counter extends StatefulWidget {

@override

_CounterState createState() => _CounterState();

}

class _CounterState extends State<Counter> {

int count = 0;

void increment() {

setState(() => count++);

}

@override

Widget build(BuildContext context) {

return Column(

children: [

Text('Count: $count'),

ElevatedButton(

onPressed: increment,

child: Text('Increment'),

),

],

);

}

}

Provider (Recommended)

Google's recommended approach for app-wide state.

// 1. Create a ChangeNotifier

class CounterModel extends ChangeNotifier {

int _count = 0;

int get count => _count;

void increment() {

_count++;

notifyListeners();

}

}

// 2. Provide it

ChangeNotifierProvider(

create: (context) => CounterModel(),

child: MyApp(),

)

// 3. Consume it

Consumer<CounterModel> (

builder: (context, counter, child) =>

Text('${ counter.count }'),

)

Riverpod (Modern)

Improved version of Provider with better safety.

final counterProvider = StateProvider((ref) => 0);

class CounterWidget extends ConsumerWidget {

@override

Widget build(BuildContext context, WidgetRef ref) {

final count = ref.watch(counterProvider);

return Text('Count: $count');

}

}

Bloc (Enterprise)

Business Logic Component pattern for large apps.

// Events

abstract class CounterEvent {}

class Increment extends CounterEvent {}

// Bloc

class CounterBloc extends Bloc<CounterEvent, int> {

CounterBloc() : super(0) {

on<Increment>((event, emit) => emit(state + 1));

}

}

Navigation & Routing

Basic Navigation:

// Push new screen

Navigator.push(

context,

MaterialPageRoute(

builder: (context) => SecondScreen(),

),

);

// Pop back

Navigator.pop(context);

// Named routes

MaterialApp(

routes: {

'/': (context) => HomeScreen(),

'/details': (context) => DetailsScreen(),

},

);

Navigator.pushNamed(context, '/details');

Platform-Specific Code

Sometimes you need different behavior for iOS and Android.

import 'dart:io' show Platform;

// Check platform

if (Platform.isIOS) {

// iOS-specific code

} else if (Platform.isAndroid) {

// Android-specific code

}

// Platform-specific widgets

import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

Platform.isIOS

? CupertinoButton(child: Text('iOS'))

: ElevatedButton(child: Text('Android'));

Hot Reload & Development

Development Workflow:

  • • Hot Reload (r): Update UI instantly, keeps state
  • • Hot Restart (R): Restart app, lose state
  • • DevTools: Inspector, performance, network
  • • Widget Inspector: Visual debugging tool
  • • Flutter Doctor: Check setup issues

Complete Todo App Example

import 'package:flutter/material.dart';

void main() => runApp(TodoApp());

class TodoApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return MaterialApp(

title: 'Todo App',

theme: ThemeData(primarySwatch: Colors.orange),

home: TodoList(),

);

}

}

class TodoList extends StatefulWidget {

@override

_TodoListState createState() => _TodoListState();

}

class _TodoListState extends State<TodoList> {

final List<String> _todos = [];

final TextEditingController _controller =

TextEditingController();

void _addTodo() {

if (_controller.text.isNotEmpty) {

setState(() {

_todos.add(_controller.text);

_controller.clear();

});

}

}

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(title: Text('My Todos')),

body: Column(

children: [

Padding(

padding: EdgeInsets.all(16),

child: Row(

children: [

Expanded(

child: TextField(

controller: _controller,

decoration: InputDecoration(

hintText: 'Enter todo',

),

),

),

SizedBox(width: 8),

ElevatedButton(

onPressed: _addTodo,

child: Text('Add'),

),

],

),

),

Expanded(

child: ListView.builder(

itemCount: _todos.length,

itemBuilder: (context, index) {

return ListTile(

title: Text(_todos[index]),

trailing: IconButton(

icon: Icon(Icons.delete),

onPressed: () => setState(() {

_todos.removeAt(index);

}),

),

);

},

),

),

],

),

);

}

}

📚 Module Summary

You've mastered Flutter and Dart:

  • ✓ Dart programming language basics
  • ✓ Flutter widgets and layouts
  • ✓ State management (setState, Provider, Riverpod, Bloc)
  • ✓ Navigation and routing
  • ✓ Platform-specific code
  • ✓ Hot reload development workflow

Next: Learn mobile UI/UX design principles!