flutter
/

GetView & GetWidget: Clean UI with GetX

Last Sync: Today

On this page

9
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

GetView & GetWidget: Clean UI with GetX

Introduction

When building Flutter apps with GetX, you often need to access controllers in your widgets. The most common way is to call Get.find<MyController>() or use Get.put and store the instance. GetX provides two dedicated widgets that reduce this boilerplate: GetView and GetWidget. These widgets automatically find and inject the controller of the specified type, making your UI code cleaner and more focused on layout.

GetView – Type‑Safe Controller Access

GetView is a generic StatelessWidget that expects a controller type T (which must extend GetxController). It provides a controller property that is automatically retrieved via Get.find<T>(). This eliminates the need to call Get.find or Get.put inside your widget.

DARTRead-only
1
class HomePage extends GetView<HomeController> {
  @override
  Widget build(BuildContext context) {
    // `controller` is already available
    return Obx(() => Text('Count: ${controller.count}'));
  }
}

Because GetView is a StatelessWidget, it does not manage the lifecycle of the controller. The controller must already be registered (e.g., via bindings or earlier Get.put).

GetWidget – Stateless with Reactive Callback

GetWidget is a simpler alternative that does not require a generic type. Instead, it provides a controller getter that returns the controller of the type you specify, but you must pass a function that returns the controller instance. It is often used when you don't need the full GetView generic, or when you need to access multiple controllers.

DARTRead-only
1
class SettingsPage extends GetWidget<SettingsController> {
  @override
  Widget build(BuildContext context) {
    // `controller` is available here as well
    return Text('Theme: ${controller.themeMode}');
  }
}

In practice, GetWidget works almost identically to GetView. The main difference is that GetWidget does not have a generic constraint (though you can still specify one). Both provide a controller getter.

GetView vs GetWidget – What’s the Difference?

In most cases, the two are interchangeable. The choice is often a matter of style. Many developers prefer GetView because it explicitly declares the controller type.

Using GetView with Bindings

For clean architecture, combine GetView with bindings. The binding registers the controller, and the view automatically finds it when built.

DARTRead-only
1
// Binding
class HomeBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut<HomeController>(() => HomeController());
  }
}

// View
class HomePage extends GetView<HomeController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Obx(() => Text('Count: ${controller.count}')),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: controller.increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

// Route registration
GetPage(
  name: '/home',
  page: () => HomePage(),
  binding: HomeBinding(),
);

Best Practices

  • Use GetView for every screen – It clearly communicates which controller the view uses.
  • Combine with bindings – Keep dependency injection out of your UI widgets.
  • Don’t put Get.put inside GetView – The controller should already be registered.
  • Use Obx or GetBuilder inside GetView for reactivity – GetView itself is not reactive; it just provides the controller.
  • Consider GetWidget for small, stateless parts – If you need a controller but prefer less generic syntax.

Common Mistakes

  • ❌ Assuming GetView creates the controller – It only finds an existing controller. ✅ Register the controller first (e.g., in a binding).
  • ❌ Using GetView without a controller registered – Throws an error. ✅ Ensure the controller is registered before the view is built.
  • ❌ Placing reactive code directly inside GetView without Obx – The UI won’t update when the controller’s reactive variables change. ✅ Wrap the reactive parts with Obx.
  • ❌ Using GetWidget with a different generic type than the registered controller – Causes a type error. ✅ Keep the generic type consistent.

FAQ

  • Q: Does GetView work with Get.lazyPut?
    A: Yes, as long as the controller is registered before the view builds. With bindings, lazyPut will create the controller when the view tries to access it.
  • Q: Can I access multiple controllers in one view?
    A: With GetView, you get one typed controller. For multiple, you can use Get.find inside the build method, or use GetWidget and call Get.find separately.
  • Q: What’s the difference between GetView and using Get.find in a StatelessWidget?
    A: GetView is simply a convenience wrapper. It reduces boilerplate and clearly indicates the controller type. There’s no performance difference.
  • Q: Can I use GetView with GetBuilder?
    A: Yes, GetBuilder works inside GetView the same way as in any StatelessWidget.
  • Q: Is GetWidget still useful?
    A: Yes, some developers prefer it for its slightly simpler syntax when they don’t need the generic type (though you can also just use a StatelessWidget with Get.find).
  • Q: Do GetView and GetWidget dispose the controller?
    A: No, they only retrieve it. Disposal is handled by GetX based on the registration options (e.g., via bindings).

Conclusion

GetView and GetWidget are simple but powerful tools that make your UI code cleaner and more maintainable. By using them consistently, you reduce the need for repetitive Get.find calls and make the relationship between your views and controllers explicit.

Try it yourself

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: GetViewExample(),
      initialBinding: HomeBinding(),
    );
  }
}

// Controller
class HomeController extends GetxController {
  var count = 0.obs;
  void increment() => count++;
}

// Binding
class HomeBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => HomeController());
  }
}

// View using GetView
class GetViewExample extends GetView<HomeController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetView Example')),
      body: Center(
        child: Obx(() => Text('Count: ${controller.count}', style: TextStyle(fontSize: 32))),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: controller.increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

Test Your Knowledge

Q1
of 3

What does GetView provide?

A
A reactive StatefulWidget
B
A stateless widget with a typed controller property
C
Automatic controller disposal
D
A replacement for GetBuilder
Q2
of 3

Where should the controller be registered when using GetView?

A
Inside GetView itself
B
In a binding or before the view is built
C
In the widget's constructor
D
In the main function
Q3
of 3

Which widget would you use to make the UI reactive inside GetView?

A
GetView
B
GetWidget
C
Obx or GetBuilder
D
GetX

Previous

getx clean architecture

Next

getx form validation

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.