Flutter Architecture Patterns — Part 1

Abdul Monem Olabi
4 min readMay 22, 2023

--

Development Process

Why we need architecture patterns

Developing classes in a random way without any planning or a good approach may lead to quick progress in the short term, but it can result in a software product that is difficult to maintain and understand in the long term. Therefore, it is important to follow a structured approach or architecture pattern in software development to ensure that the software is scalable, maintainable, and easy to understand.

Architecture patterns in programming are important because they provide a structured approach to building software applications that are easy to maintain, scale, and modify. Architecture patterns provide a blueprint for designing software applications that meet specific requirements such as performance, scalability, maintainability, and modifiability. It may take time to planning and study the structure of software, but it will give you more efficiency in future.

There are many patterns to use in your flutter projects.
We will talk about three main patterns:

· MVVM (Model, View, View-Model).

· MVC (Model, View, Controller).

· Clean architecture.

What is MVVM pattern

MVVM is a popular architecture pattern that can be used in Flutter to build scalable applications.

The terms MVVM consists of three main components:

1. Model: the main role of this layer is data structures that represent the data, implements the business logic of the application and interacts with data sources and services to retrieve and store data.

2. View: responsible for rendering the user interface, animations, and text. However, it is not directly interacted with to change its state.

3. View-Model: this layer located between Model and View and responsible for handling user input, exposes the data of the model to view layer and managing the states of view layers.

State & Data flow

Benefits of MVVM in Flutter

separates the concepts of an application into three distinct components and making the code easier to understand, maintain, and test.

Better user experience By separating the View and ViewModel layers, MVVM allows for more flexible and dynamic user interfaces that can respond to user input and changes in data quickly and efficiently.

In addition, Easier to maintain as each component has a clear responsibility.

Implementing MVVM in Flutter

Let’s talk about how we can implement each layer in Flutter.
First of all project structure can be like this:

Project structure

Model layer

We will define the data of the application in this layer.
This can include creating classes for data entities.

class User {
User({
required this.id,
required this.firstName,
required this.lastName,
this.phoneNumber,

});


int id;
String? firstName,lastName;
PhoneNumber? phoneNumber;

factory User.fromJson(Map<String, dynamic> json) => adaptJsonToUser(json);

Map<String, dynamic> toJson() => adaptUserToJson(this);
}

View-Model layer

Implementing the ViewModel layer, which is responsible for exposing the data and behavior of the Model to the View and handle application logic. It should also handle user input and update the Model accordingly. We can use the ChangeNotifier class or any other state management solution to implement the View-Model.

we will talked about state management in more details stay tuned.

class UserViewModel with ChangeNotifier {
ApiProviders _apiProviders = ApiProviders();
User? _user;
bool _isloading = false;


bool get isloading => _isloading;

set isloading(bool value) {
_isloading = value;
notifyListeners();
}

User? get user {
return _user;
}


String? get fullName {
return '${_user.firstName} ${_user.lastName}';
}

// Call Api from remote data source
// All kinds of Api exception are handled in remote data class
Future<void> fetchUserData(String value) async {
isloading = true;
try {
_user = await _apiProviders.fetchUser(value);
isloading = false;
}
}

View layer

The View layer ,which is responsible for rendering the UI of the application. The View should listen to the ViewModel and update the UI when the data changes.

Widget build(BuildContext context) {
return Consumer<UserViewModel>(
builder: (context, state, snapshot) {
return Scaffold(
key: _key,
body: state.isloading
? LoadingWidget()
: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: SvgPicture.asset(
Illustrations.profile_background,
fit: BoxFit.fitWidth,
height: 150.h,
color: Colors.black,
),
),
Center(
child: Text(
state.user!.fullName,
)),
],
),
),
);
},
);
}

In conclusion, MVVM separates the concepts of the application into three distinct components (Model, View, and View-Model), which helps to separate the application logic from the UI. This makes the code easier to understand, modify, and test, resulting in a more readable, scalable, and maintainable codebase.

We hope this introduction to architecture pattern and MVVM has provided you with a good idea.

In the next part, we will discuss MVC, its advantages, and how to implement it in Flutter.

--

--