Home > database >  How to attend best practice for not using UI code in the Controller with GetX flutter when I need to
How to attend best practice for not using UI code in the Controller with GetX flutter when I need to

Time:02-10

For a simple Email login with OTP code I have a structure as follows.

  1. View

await _signUpCntrl.signUp(email, password);

  1. Controller

_showOtpDialog(email);

  1. _showOtpDialog func
 return Get.dialog(
        AlertDialog(

So the thing is _showOtpDialog function is inside a controller file. ie. /Controllers/controller_file.dart

I want do something like a blocListener, call the _showOtpDialog from a screen(view) file on signup success. (also relocate the _showOtpDialog to a view file)

Using GetX I have to use one of the builders either obs or getbuilder. Which is I think not a good approach to show a dialog box.

On internet it says Workers are the alternative to BlocListener. However Workers function resides on Controller file and with that the dialog is still being called on the controller file.

As OTP dialog will have its own state and a controller I wanted to put it inside a /view/viewfile.dart How do I obtain this? I tried using StateMixin but when I call Get.dialog() it throw an error.

visitChildElements() called during build

CodePudding user response:

Unlike BLoC there's no BlocListener or BlocConsumer in GetX.

Instead GetX has RxWorkers. You can store your response object in a Rx variable:

class SomeController extends GetxController{

    final response= Rxn<SomeResponse>();

    Future<void> someMethod()async{

         response.value = await someApiCall();

    }
 }

And then right before the return of your widget's build method:

class SomeWidget extends StatelessWidget{
 
   final controller = Get.put(SomeController());


 @override
 Widget build(BuildContext context){

   ever(controller.response, (SomeResponse res){
        if(res.success){
          return Get.dialog(SuccessDialog()); //Or snackbar, or navigate to another page
        } 
        ....
      });

     return UI();

  }

CodePudding user response:

First thing, you will need to enhance the quality of your question by making things more clearly. Add the code block and the number list, highlight those and making emphasize texts are bold. Use the code block instead of quote.

Seconds things, Depends on the state management you are using, we will have different approaches:

  1. Bloc (As you already added to the question tag). By using this state management, you controller ( business logic handler) will act like the view model in the MVVM architecture. In terms of that, You will need to emit a state (e.g: Sent success event). Afterward, the UI will listen to the changes and update it value according to the event you have emitted. See this Bloc example

  2. GetX (As your code and question pointed out): GetX will acts a little bit different. you have multiple ways to implement this:

  • Using callbacks (passed at the start when calling the send otp function)
  • Declare a general dialog for your application ( this is the most used when it comes to realization) and calling show Dialog from Bloc
  • Using Rx. You will define a Reactive Variable for e.g final success = RxBool(true). Then the view will listen and update whenever the success changes.

controller.dart

class MyController extends GetxController {
    final success = RxBool(false);

    void sendOtp() async {
        final result = await repository.sendOTP();
        success.update((val) => {true});
    }
}

view.dart

  class MyUI extends GetView<MyController> {
      @override
      Widget build(BuildContext context) {
          ever(controller.success, (bool success) {
          // This will update things whenever success is updated
              if (success) {
                  Get.dialog(AlertDialog());
              }
          });

          return Container();
      }
  }
  • Related