Flutter Architecture

Understanding how Flutter works under the hood

🏗️ Flutter Architecture

Flutter uses a layered architecture with Framework layer for widgets, Engine layer for rendering, and Embedder layer for platform integration. Everything renders through Skia graphics engine for native performance.


// Flutter's widget tree architecture
MaterialApp
  └── Scaffold
      ├── AppBar
      └── Body
          └── Column
              ├── Text
              └── Button

// Everything is a widget!
                                    

Flutter Layers

🎨

Framework Layer

Dart code, widgets, and libraries

// Written in Dart
Text()
Container()
Scaffold()
⚙️

Engine Layer

C++ rendering engine with Skia

Skia Graphics
Dart Runtime
Text Layout
📱

Embedder Layer

Platform-specific code

Android (Java/Kotlin)
iOS (Objective-C/Swift)
Windows/Linux/Mac
🔧

Platform Channels

Communication bridge

// Access native APIs
MethodChannel
EventChannel

🔹 Widget Tree Architecture

Flutter builds UI using three trees:

1. Widget Tree (Configuration)


// Widgets are immutable configurations
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('Hello'),
    );
  }
}

// Widget tree:
// Container
//   └── Text
                            

2. Element Tree (Lifecycle)


// Elements manage widget lifecycle
// Created automatically by Flutter
// Links widgets to render objects

// Element tree mirrors widget tree
// ContainerElement
//   └── TextElement
                            

3. Render Tree (Painting)


// Render objects handle layout and painting
// Optimized for performance

// Render tree:
// RenderContainer
//   └── RenderParagraph
                            

🔹 How Flutter Renders UI

Understanding the rendering pipeline:

Rendering Steps:

  1. Build: Widgets create element tree
  2. Layout: Calculate size and position
  3. Paint: Draw widgets on screen
  4. Composite: Combine layers
  5. Rasterize: Convert to pixels (Skia)

// Flutter's rendering process
Widget build() → Element → RenderObject → Paint → Screen

// Example:
Text('Hello')           // Widget
  → TextElement         // Element
    → RenderParagraph   // RenderObject
      → Canvas.drawText // Paint
        → Screen pixels // Display
                            

🔹 Stateless vs Stateful Widgets

Two types of widgets in Flutter:

🔸 Stateless Widget (Immutable)


// Never changes after creation
class MyStatelessWidget extends StatelessWidget {
  final String title;
  
  MyStatelessWidget({required this.title});
  
  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

// Use for: Static content, labels, icons
                            

🔸 Stateful Widget (Mutable)


// Can change over time
class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int counter = 0;
  
  void increment() {
    setState(() {
      counter++;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $counter'),
        ElevatedButton(
          onPressed: increment,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

// Use for: Interactive UI, forms, animations
                            

Output:

Count: 0

🔹 State Management

Managing state in Flutter apps:


// setState() - Simple state management
class Counter extends StatefulWidget {
  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int count = 0;
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('$count'),
        ElevatedButton(
          onPressed: () {
            setState(() {
              count++; // Update state
            });
          },
          child: Text('+'),
        ),
      ],
    );
  }
}

// setState() triggers rebuild of widget
                            

🔹 BuildContext Explained

Understanding BuildContext:


// BuildContext represents widget's location in tree
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // context gives access to:
    
    // 1. Theme data
    final theme = Theme.of(context);
    
    // 2. Media query (screen size)
    final size = MediaQuery.of(context).size;
    
    // 3. Navigation
    Navigator.of(context).push(...);
    
    // 4. Inherited widgets
    final data = MyInheritedWidget.of(context);
    
    return Container();
  }
}
                            

🔹 Widget Lifecycle

Stateful widget lifecycle methods:


class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  
  @override
  void initState() {
    super.initState();
    // Called once when widget is created
    print('Widget initialized');
  }
  
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // Called when dependencies change
  }
  
  @override
  Widget build(BuildContext context) {
    // Called every time widget needs to rebuild
    return Container();
  }
  
  @override
  void didUpdateWidget(MyWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    // Called when widget configuration changes
  }
  
  @override
  void dispose() {
    // Called when widget is removed
    print('Widget disposed');
    super.dispose();
  }
}
                            

🔹 Platform Channels

Communicating with native code:


import 'package:flutter/services.dart';

// Create a method channel
class BatteryLevel {
  static const platform = MethodChannel('samples.flutter.dev/battery');
  
  Future<int> getBatteryLevel() async {
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      return result;
    } catch (e) {
      print('Error: $e');
      return -1;
    }
  }
}

// Use in widget
ElevatedButton(
  onPressed: () async {
    final battery = BatteryLevel();
    final level = await battery.getBatteryLevel();
    print('Battery: $level%');
  },
  child: Text('Get Battery'),
)
                            

🔹 Flutter Architecture Benefits

Why Flutter's Architecture is Powerful:

  • Fast Rendering: Direct compilation to native code
  • Hot Reload: Instant updates without losing state
  • Consistent UI: Same widgets on all platforms
  • Customizable: Full control over every pixel
  • Reactive: UI automatically updates with state changes

🧠 Test Your Knowledge

Which graphics engine does Flutter use for rendering?