Flutter GetX dependency Injection

Issue

I’m new to GetX flutter state management. I’m using two controllers, one for Login and other for Home data(fetching some restaurants data through API call). I’m having trouble in bindings. I’m using bindings in my app following GetX docs. But I’m unable to use it properly and getting error. Following is the code -:

main.dart

void main() async {
  await GetStorage.init('My Storage');
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flunkey Task',
      getPages: [
        GetPage(
            name: '/',
            page: () => LandingPage(),
            binding: BindingsBuilder(() {
              Get.lazyPut<LoginController>(() => LoginController());
            })),
        GetPage(
            name: '/login',
            page: () => LoginScreen(),
            binding: BindingsBuilder(() {
              Get.lazyPut<LoginController>(() => LoginController());
            })),
        GetPage(
          name: '/home',
          page: () => HomeScreen(),
          binding: BindingsBuilder(() {
            Get.lazyPut<HomeController>(() => HomeController());
          }),
        )
      ],
      initialRoute: '/',
    );
  }
}

class LandingPage extends StatelessWidget {
  LandingPage({Key? key}) : super(key: key);

  final _controller = Get.find<LoginController>();
  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);

    return Obx(() =>
        _controller.isLoggedIn.value == true ? HomeScreen() : LoginScreen());
  }
}

loginController.dart

class LoginController extends GetxController {
  final box = GetStorage('My Storage');

  var isLoggedIn = false.obs;

  final formKey = GlobalKey<FormState>();
  final usernameTED = TextEditingController();
  final passwordTED = TextEditingController();

  @override
  void onInit() {
    isLoggedIn(loginStatus);
    super.onInit();
  }

  @override
  void onClose() {
    usernameTED.dispose();
    passwordTED.dispose();
    super.onClose();
  }

  String? checkUsername(String username) {
    if (username.isEmpty || username.length < 3 || username.length > 11) {
      return 'Username must have 3-11 characters';
    }
    return null;
  }

  String? checkPassword(String password) {
    if (password.isEmpty || password.length < 3 || password.length > 11) {
      return 'Password must have 3-11 characters';
    }
    return null;
  }

  Future<void> login() async {
    if (!formKey.currentState!.validate()) {
      return;
    }

    if ((usernameTED.text.trim() == 'flunkey' &&
            passwordTED.text.trim() == 'password123') ||
        (usernameTED.text.trim() == 'user' &&
            passwordTED.text.trim() == 'password123')) {
      formKey.currentState!.save();

      await changeLoginStatus(true);
      await saveUserName(usernameTED.text);
      usernameTED.clear();
      passwordTED.clear();
    } else {
      Get.snackbar('Login Error', 'User does not exists',
          backgroundColor: Colors.red[400]);
    }
  }

  void signOut() async {
    await changeLoginStatus(false);
  }

  Future<void> changeLoginStatus(bool status) async {
    await box.write('status', status);
    isLoggedIn(status);
  }

  Future<void> saveUserName(String name) async {
    await box.write('name', name);
  }

  bool get loginStatus => box.read('status') ?? false;
  String get currentUserName => box.read('name') ?? '';
}

homeController.dart

class HomeController extends GetxController {
  final _isLoading = false.obs;
  final _restaurantData = <restau.Datum>[].obs;

  @override
  void onInit() {
    getData();
    super.onInit();
  }

  bool get isLoading => _isLoading.value;
  List<restau.Datum> get getRestaurants => _restaurantData;

  Future<void> getData() async {
    try {
      _isLoading(true);
      var apiData = await RestaurantDataApiCall.getRestaurantData();
      _restaurantData.value = apiData!.data.data;
      _isLoading(false);
    } catch (e, s) {
      print(e);
      print(s);
    }
  }
}

Following is the error I’m getting.

enter image description here

I’m using Get.find() on Login Screen and Get.find() on Home screen as following,

enter image description here

enter image description here

Please guide me how to properly use Bindings in GetX.

Solution

I don’t like to bind the controllers on route.
I create a MainBind.dart and put inside this class all getx controllers.

class MainBinding implements Bindings {

 @override
  Future<void> dependencies() async{
      Get.lazyPut<AppController>(() => AppController(), fenix: true);
  }
}

And in my Main.dart :

void main() async{
  WidgetsFlutterBinding.ensureInitialized();

  MainBinding mainBinding = MainBinding();
  await mainBinding.dependencies();

  runApp(const MyApp());

}

In this way I’m sure that Controllers are binded.
But you can try use Put insted lazyPut too..

Answered By – Sergio Clemente

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *