Search code examples
flutterdartflutter-getx

Best way to use GetxController in nested widget


In my Flutter app I use GetxController as a viewModel for every view:

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

import 'track_activity_view_model.dart';

// Main widget of the view
class TrackActivityView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetBuilder<TrackActivityViewModel>(
        init: TrackActivityViewModel(),
        builder: (viewModel) {
          return SafeArea(
              child: Scaffold(
            appBar: AppBar(title: Text('Registra un\'attività')),
            body: viewModel.serviceEnabled
                ? AskPermissionWidget()
                : TrackingWidget(viewModel),
          ));
        });
  }
}

class AskPermissionWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetBuilder<TrackActivityViewModel>(
        init: TrackActivityViewModel(),
        builder: (viewModel) {
          // Some code that use viewModel
          return Container();
        });
  }
}

class TrackingWidget extends StatelessWidget {
  final TrackActivityViewModel viewModel;

  TrackingWidget(this.viewModel);

  @override
  Widget build(BuildContext context) {
    // Some code that use viewModel    
    return Container();
  }
}

When I write some nested widget, I'm wondering if is it better

  1. Call the controller ex-novo (AskPermissionWidget)

or

  1. Pass the controller as a parameter (TrackingWidget)

Are there any differences?

Thank-you very much.


Solution

  • In GetX you need not to struggle anymore with dependency injection (this is the title of what you asked). Even it is one of the main benefits of GetX over other packages.

    You need to do following steps to get the things around:

    1. Just create (and bind) your ViewModel(s) (or better named Controllers) using :

      a. Get.put or Get.lazyPut methods used in constructor or build method of the top widget

      b. or using init parameter of GetBuilder in the top widget to construct a new controller

      c. or using Bindings for any page to define the Controllers related to that page.

    2. Find your Controller in the child widgets or anywhere else using myViewModel = Get.find<MyViewModel>(). You need not any more to initialize it in the child or pass it within constructors. It always find the right Controller for you. Or if you want it to be used in GetBuilder you could use the GetBuilder in the child without any init paramter or anything else. Just write this in your child widget :

        return GetBuilder<TrackActivityViewModel>(
            builder: (viewModel) {
              // Some code that use viewModel
              return Container();
            });
    

    and the GetBuilder itself finds the right Controller for you. No need to pass it anything else (after you ensured that the controller is initialized in a top widget or it is a permanent controller which will not be removed from the memory).

    Isn't it simple ?! As I mentioned, this is the major advantage of GetX over the other state management packages.

    note : If you want multiple instances of a single Controller class, you would be able to pass a unique tag parameter in Get.put or Get.lazyPut or in the GetBuilder or GetX widget to uniquely define the Controller and then in the child widgets or anywhere you want to find it use that unique tag to identify which one do you want.

    Summary : GetX always finds the right Controller.