Question #21MediumFlutter Basics

Usage of getbuilder in flutter

#flutter

Answer

Overview

GetBuilder is a lightweight state management widget from the GetX package. It rebuilds only when explicitly notified, making it more efficient than Obx for non-reactive state updates.


GetBuilder vs Obx

FeatureGetBuilderObx
Reactive❌ No✅ Yes
Rebuild TriggerManual (update())Automatic (.obs)
MemoryLowerHigher
PerformanceFasterSlightly slower
Use CaseComplex widgetsSimple reactive UI
SyntaxMore verboseCleaner

Basic Usage

Step 1: Install GetX

yaml
dependencies:
  get: ^4.6.0

Step 2: Create Controller

dart
import 'package:get/get.dart';

class CounterController extends GetxController {
  int count = 0; // Not reactive (.obs not needed)
  
  void increment() {
    count++;
    update(); // Manually trigger rebuild
  }
  
  void decrement() {
    count--;
    update(); // Must call update()
  }
  
  void reset() {
    count = 0;
    update();
  }
}

Step 3: Use GetBuilder

dart
class CounterScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetBuilder Demo')),
      body: Center(
        child: GetBuilder<CounterController>(
          init: CounterController(), // Initialize controller
          builder: (controller) {
            return Text(
              'Count: ${controller.count}',
              style: TextStyle(fontSize: 32),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Get.find<CounterController>().increment();
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

Advanced Features

1. Selective Rebuild with ID

Only rebuild specific GetBuilders.

dart
class TodoController extends GetxController {
  List<String> todos = [];
  int completedCount = 0;
  
  void addTodo(String todo) {
    todos.add(todo);
    update(['todo-list']); // Only rebuild widgets with id 'todo-list'
  }
  
  void incrementCompleted() {
    completedCount++;
    update(['counter']); // Only rebuild widgets with id 'counter'
  }
}

// UI
GetBuilder<TodoController>(
  id: 'todo-list', // This widget only rebuilds when update(['todo-list']) is called
  builder: (controller) {
    return ListView.builder(
      itemCount: controller.todos.length,
      itemBuilder: (context, index) => Text(controller.todos[index]),
    );
  },
)

GetBuilder<TodoController>(
  id: 'counter', // This widget only rebuilds when update(['counter']) is called
  builder: (controller) {
    return Text('Completed: ${controller.completedCount}');
  },
)

2. Conditional Rebuild

dart
class UserController extends GetxController {
  String name = '';
  int age = 0;
  
  void updateName(String newName) {
    name = newName;
    update(); // Rebuild all
  }
  
  void updateAge(int newAge) {
    age = newAge;
    update((ids) => ids.contains('age-display')); // Conditional rebuild
  }
}

3. Auto Dispose

dart
GetBuilder<CounterController>(
  init: CounterController(),
  dispose: (state) => Get.delete<CounterController>(), // Auto cleanup
  builder: (controller) => Text('${controller.count}'),
)

Complete Example

dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';

// Controller
class ThemeController extends GetxController {
  bool isDarkMode = false;
  int fontSize = 16;
  
  void toggleTheme() {
    isDarkMode = !isDarkMode;
    update(['theme']); // Only rebuild theme-related widgets
  }
  
  void increaseFontSize() {
    fontSize++;
    update(['font']); // Only rebuild font-related widgets
  }
  
  void decreaseFontSize() {
    fontSize--;
    update(['font']);
  }
}

// Screen
class SettingsScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Settings')),
      body: Column(
        children: [
          // Theme Toggle
          GetBuilder<ThemeController>(
            init: ThemeController(),
            id: 'theme',
            builder: (controller) {
              return SwitchListTile(
                title: Text('Dark Mode'),
                value: controller.isDarkMode,
                onChanged: (_) => controller.toggleTheme(),
              );
            },
          ),
          
          // Font Size Control
          GetBuilder<ThemeController>(
            id: 'font',
            builder: (controller) {
              return Column(
                children: [
                  Text(
                    'Preview Text',
                    style: TextStyle(fontSize: controller.fontSize.toDouble()),
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      IconButton(
                        icon: Icon(Icons.remove),
                        onPressed: controller.decreaseFontSize,
                      ),
                      Text('${controller.fontSize}'),
                      IconButton(
                        icon: Icon(Icons.add),
                        onPressed: controller.increaseFontSize,
                      ),
                    ],
                  ),
                ],
              );
            },
          ),
        ],
      ),
    );
  }
}

void main() {
  runApp(GetMaterialApp(home: SettingsScreen()));
}

GetBuilder vs setState

dart
// With setState
class CounterScreen extends StatefulWidget {
  
  _CounterScreenState createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int count = 0;
  
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('$count')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => count++),
      ),
    );
  }
}

// With GetBuilder
class CounterScreen extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: GetBuilder<CounterController>(
          init: CounterController(),
          builder: (c) => Text('${c.count}'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => Get.find<CounterController>().increment(),
      ),
    );
  }
}

When to Use GetBuilder

✅ Use GetBuilder When:

  • Performance is critical
  • Complex widgets with expensive builds
  • Need fine-grained rebuild control (IDs)
  • Non-reactive state updates
  • Large lists or grids

❌ Don't Use GetBuilder When:

  • Simple reactive state (use Obx)
  • Real-time updates (use Obx)
  • Two-way binding needed (use .obs)

Best Practices

Tip: Use IDs to rebuild only necessary widgets

dart
// ✅ Good - Selective rebuild
void updateName() {
  name = newName;
  update(['name-display']);
}

// ❌ Bad - Rebuilds everything
void updateName() {
  name = newName;
  update();
}

Initialize Controllers Properly

dart
// ✅ Good - Use Get.put() or init in GetBuilder
Get.put(CounterController());

// Or
GetBuilder<CounterController>(
  init: CounterController(),
  ...
)

// ❌ Bad - Creating new instance every build
GetBuilder<CounterController>(
  builder: (_) => CounterController(), // Wrong!
)

Resources