I don't know how to separate responsibilities when tapping buttons.

Asked 1 years ago, Updated 1 years ago, 230 views

Which do you think is the best way to write specific things to the view side like Method 1 or to write a tap process like ButtonTapAction and write the contents on the viewModel (Controller)?
Personally, I think it's the latter.
As a benefit, I found the methods of models such as takePicture and savePhotoFromDevice easy to test.

There are three things that I am worried about, and first of all, there are few sample codes in other articles.
When I checked the article where I took the picture, I found that most of the articles were called takePicture() method in view onTap.

Another concern is that buttonTapAction tends to have more arguments.
Finally, let's say that the tap process is summarized in viewModel in a complicated state such as taking pictures with tap processing or saving photos on a device like this.In that case, you will never know what the view side is doing like ButtonTapAction.
I would appreciate your advice.Please.

ElevatedButton(
            // What to do when you tap a button?               
           onPressed:() async {
              try{
                 // the process of taking a photographically
           viewModel.takePicture();            
          // The process of storing photos on a device.
                  viewModel.savePhotoFromDevice();
          // What to do to save to local DB
                 viewModel.updateDb();
              } on Exception catch(e){
                   logger.i(e);
                }
             },
         child:const Text('Take a Camera'),
    ),
ElevatedButton(
            // What to do when you tap a button?               
           onPressed:() async {
              try{
                // Function to tap Button
                viewModel.buttonTapAction();
              } on Exception catch(e){
                   logger.i(e);
                }
             },
         child:const Text('Take a Camera'),
    ),
class ViewModel {
  var counter1 = 0;
  var counter2 = 0;
  void buttonTapAction() {
   // the process of taking a photographically
  model.takePicture();            
  // The process of storing photos on a device.
   model.savePhotoFromDevice();
  // What to do to save to local DB
    model.updateDb();
    changeCounter1();
    changeCounter2();
  }
  
  void changeCounter1() {
    counter1++;
    notifylists();
  }

   void changeCounter2() {
    counter2++;
    notifylists();
  }
}

flutter mvvm

2023-02-01 11:02

1 Answers

Personally, I prefer ViewModel calls only on the View side.

You push everything you try into the ViewModel as follows.

ElevatedButton(
        // What to do when you tap a button?               
        onPressed: viewModel.buttonTapAction,
        child:const Text('Take a Camera'),
    ),

    classViewModel {
      void buttonTapAction() {
       try{
           // the process of taking a photographically
         model.takePicture();            
         // The process of storing photos on a device.
          model.savePhotoFromDevice();
         // What to do to save to local DB
          model.updateDb();
       } on Exception catch(e){
           logger.i(e);
       }
      }
    }

The View side has no processing, so it's easy to do a single test, and the ViewModel side has a complete processing, so it's easy to do a test.

Finally, let's say that the tap process is summarized in viewModel in a complicated state such as taking pictures with tap processing or saving photos on a device like this.In that case, you will never know what you are doing on the view side like ButtonTapAction.

I think that's what MVVM is all about.
The View side informs the ViewModel side that there was an event when an event occurred in the UI in the basic UI partial main.ViewModel will do something about the events that occur.

I don't know what makes you feel complicated when you say "complex."
Considering the specifications of the package to be used, if you design it including screen transitions and state transitions, there will be no problem.

If anything, Flutter's packages are weak in documentation or have few examples on the web, so I don't know what you're trying to say, so it might be hard to make samples yourself and put them into your knowledge as you move.

Also, I believe that the best solution to the design depends on the individual's sense or project policy.

Below is a response to the comments.

1st point: Added a method to update the status management to the above code. At that time, the UI will be updated when the button is tapped, so I thought it would be better to use a method name that can be understood by the view side.Please give us your opinion on this.

Please do something about the method name according to your personal preference.
Also, I think that the naming convention is decided among the projects.
Please follow it

Second point: If you define all of the contents of buttonTapAction in viewModel, you may have context in the arguments of the viewModel method, for example, using the showDialog method to alert when tapping the button. Also, it feels unnatural that the viewModel can display UI such as alerts and indicators simply because some views are displayed in the viewModel. If the viewModel contains context and the viewModel displays UI, I would like to know if there are any problems with these two points.

There is also a package that does not require the context to be delivered from the upper side.
I use a package called GetX, and I can get the latest context globally.If you use it incorrectly, there will be a problem (side effect), so you need to be careful.

Alternatively, you can pass the context to ViewModel as an argument.

"Also, ""The unnaturalness of some views being displayed in the viewModel"" is just my imagination."That's what I think.
Instead of having the feeling that View is displayed, it's like calling an API to get the results.In that sense, I think it will feel no different from data acquisition from DB.
If you write a little bit of a View implementation on the ViewModel, you'll feel less like that, so you just need to classify (encapsulate) View calls and their data retrieval.
This makes it easier to test individually for each class.


2023-02-01 21:13

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.