Flutterexperts

Empowering Vision with FlutterExperts' Expertise
Design Patterns in Flutter- Part 2(MVP)

In the previous blog of this series, we saw what actually design pattern is and how it is different from Software Architecture. for more explanation, I would suggest you guys go through my previous blog for clearing basic concepts of design patterns.

So wrapping Design Patterns in simple lines

Design patterns are used for separating the Main code (Business Logic) from the UI part which will make your code more readable and very easy in testing.

What is the MVP?

MVP stands for Model View Presenter, As we could see that it consists of three words so talking about them a little bit.

  • Model: It is an interface defining the data to be displayed or otherwise acted upon in the user interface.
  • View: It is a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.
  • Presenter: It acts upon the model and the view. It retrieves data from repositories (the model) and formats it for display in the view.

So We would be knowing more about these terms from our Demo App which shows a basic increment and decrement counters.

Communication Flow

We will see from this Flow Diagram that how model view and presenter are connected to make our code more readable and easier in testing.

MVP consists of model view and presenter and they are bonded in such a way that View in the topmost layer which is responsible for showing the data to the user and taking data from the user, Presenter being in the middle of View and Model takes the input from View and taking the data from Model. the Presenter contains the UI business logic for the View. All invocations from the View delegate directly to the Presenter. The Presenter is also decoupled directly from the View and talks to it through an interface. This is to allow mocking of the View in a unit test. The View and Model are entirely shielded from one another. The Model may raise events, but the Presenter subscribes to them for updating the View. The Model is the layer providing the data source to the user in any format.

How MVP is different from MVC?

MVP is the derivative of MVC, The key difference between MVC and its derivatives is the dependency each layer has on other layers, as well as how tightly bound they are to each other. For establishing the difference between these two design patterns, we will take the help of the flow diagram of both the design patterns to find out the difference in the way to find out how they are helpful in their own way.

As we could see from the flow diagram of MVC that the View is the one that interacts with the user, and it notifies the controller. The controller modifies some of the model based on user interaction. The Controller gets updated data on which models perform some business logic. The view gets updated once the controller passes the new data which has been received from the model. According to this, we could say about MVC that

  • Controllers are based on behaviors and can be shared across views
  • Can be responsible for determining which view to display

Now Coming to MVP, This Flow diagram shows that the flow chart is almost the same as it is in the case of MVC, but here the Controller is being replaced by Presenter. The view is the topmost layer of the architecture, interacts with the user and takes the input which is being passed to the presenter, and taking the data from the model it sends the data back to the View to present it to the user. So According to this, we could say about MVP that

  • The view is more loosely coupled to the model. The presenter is responsible for binding the model to the view.
  • Easier to unit test because interaction with the view is through an interface.
  • Usually view to presenter map one to one. Complex views may have multi presenters.

Code Understanding:

If you have not installed the flutter SDK or you are still getting familiar with it :

Let’s dive into the code part for an In-depth understanding of the process:-

1. Firstly, Create a new project and then clear all the code in the main.dart file. Type below command in your terminal:-

flutter create yourProjectName
  • Add the current latest version of MVP pattern package under the dependencies in pubspec.yaml file.
dependencies:   
mvp: ^1.0.0

Create a Model Class:

As Explained above a model class is created for both counter:-

class CounterModel {
int counter = 0;

CounterModel(this.counter);
}

Create the Presenter Class:

The Presenter is Created as this Basically Ensures the interaction with the model :

import 'package:fluttermvpdemo/model/CounterModel.dart';
import 'package:fluttermvpdemo/view/Counter.dart';

class Presenter {
void incrementCounter() {}
void decrementCounter() {}
set counterView(Counter value) {}
}

class BasicCounterPresenter implements Presenter {

CounterModel _counterViewModel;
Counter _counterView;

BasicCounterPresenter() {
this._counterViewModel = new CounterModel(0);
}

@override
void incrementCounter() {
this._counterViewModel.counter++;
this._counterView.refreshCounter(this._counterViewModel);
}

@override
void decrementCounter() {
this._counterViewModel.counter--;
this._counterView.refreshCounter(this._counterViewModel);
}

@override
set counterView(Counter value) {
_counterView = value;
this._counterView.refreshCounter(this._counterViewModel);
}


}

Adapting it Into The View :

The controller is then bound to the view.dart file so that the increment and decrement functionality may work as depicted.

class HomePage extends StatefulWidget {
final Presenter presenter;

HomePage(this.presenter, {Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<HomePage> implements Counter {
CounterModel _viewModel;

@override
void initState() {
super.initState();
this.widget.presenter.counterView = this;
}

@override
void refreshCounter(CounterModel viewModel) {
setState(() {
this._viewModel = viewModel;
});
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 30.0),
child: Text(
"Click buttons to add and substract.",
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FloatingActionButton(
onPressed: () {
this.widget.presenter.decrementCounter();
},
tooltip: 'Decrement',
child: Icon(Icons.remove),
),
Text(
_viewModel?.counter.toString(),
style: Theme.of(context).textTheme.display1,
),
FloatingActionButton(
onPressed: () {
this.widget.presenter.incrementCounter();
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
],
),
],
),
),
);
}
}

Find the code version on github at:

flutter-devs/Flutter_MVP_Demo
A new Flutter application. This project is a starting point for a Flutter application. A few resources to get you…github.com

Closing Thoughts

Design Pattern is a Quintessential tool in large scale apps in native applications which you can also practice in flutter also. In this Blog, the only MVP has been explained but this will a series of blogs, and in the next blogs, we will be sharing about MVVM, CLEAN, etc.

If you have not used Design Patterns in Flutter, I hope this article has provided you with valuable information about what is all about it, and that you will give it Design Patterns — a Try. Begin using them for your Flutter Apps !!

You can find each part of this series for the posts in the links below:

Feel free to connect with us:

And read more articles from FlutterDevs.com

FlutterDevs has been working on Flutter for quite some time now. You can connect with us on Facebook and Twitter for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #Flutter. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!

Thank you for reading. 🌸

Leave comment

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