Shubham Vimal
Shubham Vimal

Reputation: 55

Flutter GetX dependency Injection

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.

Upvotes: 0

Views: 5510

Answers (2)

Mykola Meshkov
Mykola Meshkov

Reputation: 107

You can use StatefulWidget with state class which will contain your controller.

E.g.

StateClass bla, bla {
  late final yourController = Get.put<YourController>();

  @override
  dispose() {
    Get.delete<YourController>();
  }
}

That's it!

Upvotes: 0

Sergio Clemente
Sergio Clemente

Reputation: 888

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..

Upvotes: 7

Related Questions