Using MVVM in Flutter (2022)
Tags: flutter, productivity, programming, dart
Published: 2022-09-04 01:03:34

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:paragraph -->
<p>We will cover briefly:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>What is MVVM</li><li>Using MVVM in Flutter</li><li>Extending MVVM with Repository and Services</li></ol>
<!-- /wp:list -->

{% youtube 7Q9dxzIo314 %}

<!-- wp:heading {"level":3} -->
<h3>What is&nbsp;MVVM</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><strong>Model-View-ViewModel (MVVM)</strong> is a software architectural pattern that supports the separation of the UI (which is <strong>View</strong>) from the development of the business logic or the backend logic (<strong>Model</strong>). The view model inside MVVM is the bridge responsible for the conversion of data in a way that behaves in accordance with the changes happening on the UI</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In addition, to know about the responsibilities of the three components, it’s also important to understand how the components interact with each other. At the highest level, <em>the view “knows about” the view model</em>, and <em>the view model “knows about” the model</em>, but <em>the model is unaware of the view model</em>, and the <em>view model is unaware of the view</em>.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<figure class="wp-block-image aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/0*Plj_xKz_2EwTrXQz.png" alt="MVVM Architecture"/><figcaption>MVVM Architecture</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>There are several advantages of using MVVM:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong>Separation of Concerns</strong>: It is a design principle for separating a computer program into distinct sections such that each section addresses a separate concern.&nbsp;<br>A concern is anything that matters in providing a solution to a problem.</li><li>Improved Testability</li><li>Defined Project Structure</li><li>Parallel development of UI</li><li>Abstract the View, thus reducing the quantity of business logic required in the code behind it</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Some disadvantages of using MVVM:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>It has a slightly steep learning curve. How all the layers work together may take some time to understand.</li><li>It adds a lot of extra classes, so it’s not ideal for low-complexity projects.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Since architectural or design patterns are platform-agnostic, they can be used with any framework, in our case <strong>Flutter</strong>.</p>
<!-- /wp:paragraph -->

{% youtube naOmmUHJMsQ %}

<!-- wp:heading {"level":4} -->
<h4>Components</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><strong>Model: </strong>This is basically the domain model or the model which represents the data from your backend (aka data access layer). Models hold information, but typically don’t handle behavior. They don’t format information or influence how data appears. The Model in the MVVM design pattern represents the actual data that will be used in application development</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>View: </strong>This is basically the only part of the application users actually interact with. For instance, the user presses the button, scrolls the list, edits the settings, etc and these events are then forwarded to the view model which then does the processing and returns the expected user response (which is some form of UI). It’s important to remember the <strong>View</strong> isn’t responsible here for handling the state.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><strong>A </strong><code>View</code><strong> should be as dumb as possible. </strong>Never put your business logic in<strong> </strong><code>Views</code><strong>.</strong></p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p><strong>View Model: </strong>The ViewModel acts as an intermediate between the <strong>View</strong> and the <strong>Model</strong>, in such a way that it provides data to the UI. The ViewModel may also expose methods for helping to maintain the View’s state, update the model based on the action’s on a View, and trigger events on the View. For <strong>Flutter, </strong>we have a listener called <code><a href="https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html" rel="noreferrer noopener" target="_blank">ChangeNotifier</a></code> that allows ViewModel to inform or update the View whenever the data get updated.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The ViewModel has basically two responsibilities:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>it reacts to user inputs (e.g. by changing the model, initiating network requests, or routing to different screens)</li><li>it offers output data that the View can subscribe to</li></ul>
<!-- /wp:list -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>In summary, the ViewModel sits behind the UI layer. It exposes data needed by a View and can be viewed as the source our Views go to for both data and actions.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:heading {"level":4} -->
<h4>What is ChangeNotifier?</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><a href="https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html" rel="noreferrer noopener" target="_blank">ChangeNotifier</a> is a class that provides change notifications to its listeners.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As per the official <a href="https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html" rel="noreferrer noopener" target="_blank">documentation</a></p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>A class that can be extended or mixed in that provides a change notification API using <a href="https://api.flutter.dev/flutter/dart-ui/VoidCallback.html" rel="noreferrer noopener" target="_blank">VoidCallback</a> for notifications.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>It is O(1) for adding listeners and O(N) for removing listeners and dispatching notifications (where N is the number of listeners).</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>There are several ways to consume the change notifier in Flutter.</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Using&nbsp;<code>.addListener</code> method, as the ChangeNotifier is a type of <a href="https://api.flutter.dev/flutter/foundation/Listenable-class.html" rel="noreferrer noopener" target="_blank">Listenable</a>.</li><li>Using the combination of <code>ChangeNotifierProvider</code>, Consumer, and Provider. These all capabilities are provided to us by the <a href="https://pub.dev/packages/provider" rel="noreferrer noopener" target="_blank">Provider</a> package.</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>We will use approach 2</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In the real world, other classes can <em>listen</em> to an <code>ChangeNotifier</code> object. When the change notifier gets updated values, it can call a method called <code><a href="https://api.flutter.dev/flutter/foundation/ChangeNotifier/notifyListeners.html" target="_blank" rel="noreferrer noopener">notifyListeners</a></code>and then any of its listeners will receive the updated val</p>
<!-- /wp:paragraph -->

```dart
class Person extends ChangeNotifier {
  Person({this.name, this.age});
  final String name;
  int age;
         
  void increaseAge() {
    this.age++;
    notifyListeners();
  }
}
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => Person(name: "Joe", age: 28),
      child: MyApp(),
    ),
  );
}
```
<!-- wp:paragraph -->
<p>Inside the app, any class that listens to this <code>Person</code> will be notified in case the <code>age</code> changes. Internally, <code>notifyListeners</code> calls the registered listeners.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Using MVVM in&nbsp;Flutter</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Flutter is declarative in nature. This means that Flutter builds UI by overriding your build methods to reflect the current state of your app:</p>
<!-- /wp:paragraph -->

```dart
UI = fn(state)
```

<!-- wp:paragraph -->
<p>According to the <a href="https://docs.flutter.dev/development/data-and-backend/state-mgmt/ephemeral-vs-app" rel="noreferrer noopener" target="_blank">Flutter documentation</a>, the state is described as “ data you need to rebuild your UI at any point in time.”</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>A state can either be contained in a single widget, known as a local state. Flutter provides inbuilt classes and methods to deal with self-contained states like <code>StatefulWidget</code> and <code>setState</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>However, a state that has to be shared across different widgets is known as an app state. It is at this point we introduce state management tools.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>We will be using <a href="https://pub.dev/packages/provider" rel="noreferrer noopener" target="_blank">Provider</a> for the state management.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Let’s say you were to architect an application that includes only the below screen. How would you do?</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><em>Hint: Using MVVM</em></p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<figure class="wp-block-image aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*KG0NtOrb3RIKXR4HJ2Amfw.png" alt="Sample Screen"/><figcaption>Sample Screen</figcaption></figure>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Each screen should comprise its own folder. Create a folder called <code>home</code> which contains a view called <code>home_view</code></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Naming convention</strong>: Each screen is called view and the file is suffixed with <code>_view</code> The view will be listening to the changes happening on the view model, using the <code><a href="https://pub.dev/documentation/provider/latest/provider/Consumer-class.html" rel="noreferrer noopener" target="_blank">Consumer</a></code></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Each view should have a view model associated with it. Create a file called <code>home_view_model</code> which will be responsible for accepting the user interactions, processing them by running some business logic, and finally responding back.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Naming convention</strong>: Each screen has a view model associated with it and the file is suffixed with <code>_view_model</code> The view model notifies the changes to the UI (if any) using the <code><a href="https://api.flutter.dev/flutter/foundation/ChangeNotifier/notifyListeners.html" rel="noreferrer noopener" target="_blank">notifyListeners</a></code></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Assuming the button calls some API (more on that later) and responds back with some response. This response should be converted as a model suffixed with <code>_model</code> and returned from the view model to the view.</li></ul>
<!-- /wp:list -->

<!-- wp:image {"align":"center"} -->
<figure class="wp-block-image aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*7kmY0bEok_LIUyU9Iv8akA.png" alt="MVVM Project Structure"/><figcaption>MVVM Project Structure</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>This is the basics of MVVM, as we can see in the screenshot above. This can be replicated for all the screens of your app. Now, let’s see slight addition on top of this structure.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Extending MVVM with Repository and&nbsp;Services</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In the real world, our app needs to interact with APIs or 3rd party integrated services. So here we introduce something called as <code>Repository</code>&nbsp;.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>A repository pattern provides an abstraction of data so that your application can work with a simple abstraction that has an interface. Using this pattern can help achieve loose coupling. If implemented correctly, the Repository pattern can be a great way to ensure you follow the <strong>Single Responsibility Principle</strong> for your data access code</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Some benefits of using the Repository pattern:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Separate the business logic for accessing external services.</li><li>Makes mocking easier and allows to do unit tests.</li><li>We can easily switch data sources without doing time-consuming code changes</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Some disadvantages of using the Repository pattern:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Adds another layer of abstraction which adds a certain level of complexity making it overkill for small applications.</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Continuing with the previous example, let’s say our button needs to call an API, let’s implement it using <code>Repository</code> pattern.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Dart has no interfaces like Java but we can create it with an abstract class. We begin by creating an abstract class that defines the interface for our <code>home_repo</code></p>
<!-- /wp:paragraph -->

```dart
abstract class HomeRepository {
  Future<CarouselModel> fetchData();
}
```

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>This abstract class helps to create a boundary, and we are free to work on either side of that boundary. We could work on implementing the home repository (<code>recommended</code>), or we could just use the implementation directly in our app (<code>not recommended</code>).</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Here, the <code>HomeRepository</code> has only one method which is <code>fetchData</code> and this method returns the response as a model called <code>CarouselModel</code>&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next, let’s implement the <code>HomeRepository</code> </p>
<!-- /wp:paragraph -->

```dart
class HomeRepositoryImpl extends HomeRepository {
  @override
  Future<CarouselModel> fetchData() async {
    await Future.delayed(const Duration(milliseconds: 1800));
    final resp = await rootBundle.loadString('assets/data/first_screen.json');
    return carouselModelFromJson(resp);
  }
}
```
<!-- wp:paragraph -->
<p>Inside the method <code>fetchData</code>we introduce a delay and then load the data from the assets which is a JSON file. This delay is basically a substitute for calling the API, <em>but I hope I am able to convey my thoughts to the reader.</em></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As your application grows, you may find yourself adding more and more methods to a given repository. In this scenario, consider creating multiple repositories, and keeping related methods together.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<figure class="wp-block-image aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*q1BNWS5-00kEkAVE3ob9qw.png" alt="Repository Pattern"/><figcaption>Repository Pattern</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>So till now, we have</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><code>carousel_model</code> representing the <strong>Model (M)</strong></li><li><code>home_view</code> representing the <strong>View (V)</strong></li><li><code>home_view_model</code> representing the <strong>View Model (VM)</strong></li><li><code>home_repo</code> representing the <strong>Repository</strong></li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":4} -->
<h4>Register the Repository</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Since our repository is ready, now we need to figure out how to register it and make it available inside our app. This is the time we introduce another concept called DI aka Dependency Injection. We make use of the package <code><a href="https://pub.dev/packages/get_it" rel="noreferrer noopener" target="_blank">get_it</a></code> As per the documentation:</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>This is a simple Service Locator for Dart and Flutter projects with some additional goodies highly inspired by <a href="https://github.com/reactiveui/splat" rel="noreferrer noopener" target="_blank">Splat</a>. It can be used instead of <code>InheritedWidget</code> or <code>Provider</code> to access objects e.g. from your UI.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p><strong>GetIt is super fast</strong> because it uses just an <code>Map&lt;Type&gt;</code> inside which makes access to it <strong>O(1). </strong>GetIt itself is a singleton so you can access it from everywhere using its <code>instance</code> property (see below).</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>We install <code>get_it</code> it by including it inside the <code>pubspec.yaml</code> as</p>
<!-- /wp:paragraph -->

```dart
dependencies:
  get_it: ^7.2.0
```

<!-- wp:paragraph -->
<p>Typically at the start of your app, you register the types that you want later access from anywhere in your app. After that, you can access instances of the registered types by calling the <code>locator</code> again.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The nice thing is you can register an interface or abstract class together with a concrete implementation. When accessing the instance you always ask for the interface/abstract class type. This makes it easy to switch the implementation by just switching the concrete type at registration time.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>We create a file called as <code>locator.dart</code> inside which we will instantiate the object of <code>get_it</code>&nbsp;</p>
<!-- /wp:paragraph -->

```dart
final GetIt locator = GetIt.instance;
void setupLocator() {
  locator.registerFactory<HomeRepository>(() => HomeRepoImpl());
  // Alternatively you could write it
  GetIt.I.registerFactory<HomeRepository>(HomeRepoImpl());
}
```

<!-- wp:paragraph -->
<p>As Dart supports global variables we assign the GetIt instance to a global variable to make access to it as easy as possible. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Although GetIt is a singleton we will assign its instance to a global variable <code>locator</code> to minimize the code for accessing GetIt. Any call to <code>locator</code> in any package of a project will get the same instance of <code>GetIt</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next, we use the <code>locator</code> and use the <code>registerFactory</code> to register our <code>HomeRepository</code>&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Provider as an alternative to GetIt</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The provider is a powerful alternative to GetIt. But there are some reasons why people use GetIt for Dependency injection:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Provider needs a <code>BuildContext</code> to access the registered objects, so you can’t use it inside business objects outside the Widget tree or in a pure dart package.</li><li>The provider adds its own Widget classes to the widget tree that are no GUI elements but are needed to access the in Provider registered objects.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Testing Repository</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can implement unit testing for different elements of your Flutter applications, such as widgets, controllers, models, services, and repositories. It’s possible to unit-test repository-based Flutter codebases with the following strategies:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Implement a mock repository class and test the logic</li><li>You don’t need to implement mock classes by yourself — the <a href="https://pub.dev/packages/mockito" rel="noreferrer noopener" target="_blank">Mockito package</a> helps you to generate them quickly and <a href="https://medium.com/flutter-community/using-mockito-in-flutter-cd015d338277?source=your_stories_page-------------------------------------" target="_blank" rel="noreferrer noopener">automatically</a>.</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":4} -->
<h4>Integrate Repository in ViewModel</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Now comes the time to use the Dependency Injection. But before that let’s see what is it.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>When class A uses some functionality of class B, then its said that class A has a dependency of class B.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Before we can use methods of other classes, we first need to create the object of that class (i.e. class A needs to create an instance of class B).</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>So, transferring the task of creating the object to someone else and directly using the dependency is called dependency injection.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<figure class="wp-block-image aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/0*0r7__ZZKUzZLQbt_.png" alt="Dependency Injection"/><figcaption>Dependency Injection</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p><strong>Benefits of using DI</strong></p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Supports Unit testing.</li><li>Boilerplate code is reduced, as initializing of dependencies is done by another component (<code>locator</code> in our case)</li><li>Enables loose coupling.</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Drawbacks of using DI</strong></p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>It’s complex to learn, and if overused can lead to management issues and other problems.</li><li>Many compile time errors are pushed to run-time.</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Coming back to our application, let’s see how we integrate.</p>
<!-- /wp:paragraph -->

```dart
class HomeViewModel extends ChangeNotifier {
  HomeViewModel({
    required this.homeRepo,
  });
  final HomeRepository homeRepo;
}
```

<!-- wp:paragraph -->
<p>Here, we create a constructor inside our <code>HomeViewModel</code> and specify the <code>homeRepo</code> as our required parameter. This way we direct that whosoever needs access to our view model will first have to pass the <code>homeRepo</code>&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Initialize the service locator</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You need to register the services on app startup, so you can do that in <code><em>main.dart</em></code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Replace the standard</p>
<!-- /wp:paragraph -->

```dart
void main() => runApp(MyApp());
```
<!-- wp:paragraph -->
<p>with the following:</p>
<!-- /wp:paragraph -->

```dart
import 'locator.dart';

void main() {
  // INIT SERVICE LOCATOR  
  setupLocator();
  
  runApp(MyApp());
}
```
<!-- wp:paragraph -->
<p>This will register any services you have with GetIt before the widget tree gets built.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>And if we recall, our <code>homeRepo</code> was registered inside the <code>locator</code> So in order to declare our view model, we follow this</p>
<!-- /wp:paragraph -->

```dart
Future<void> main() async {
   
  setupLocator();
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => HomeViewModel(repo: locator<HomeRepo>()),
        ),
      ],
      child: MainApp(),
    ),
  );
}
```

<!-- wp:paragraph -->
<p>Inside our <code>main</code> we call the <code>setupLocator</code> which is the method that comprises all the registered dependencies under <code>locator.dart</code> </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next, inside our <a href="https://pub.dev/documentation/provider/latest/provider/MultiProvider-class.html" rel="noreferrer noopener" target="_blank">MultiProvider</a>, we specify the <code>HomeViewModel</code> under the <a href="https://pub.dev/documentation/provider/latest/provider/ChangeNotifierProvider-class.html" rel="noreferrer noopener" target="_blank">ChangeNotifierProvider</a></p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>ChangeNotifierProvider creates a ChangeNotifier using <code>create</code> and automatically disposes it when it is removed from the widget tree.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:heading {"level":4} -->
<h4>Using ViewModel inside the&nbsp;View</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>We have our repository registered and passed as a required parameter to our view model. Let’s see how to use the view model inside our view.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>There are two ways to access the view model inside the view</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Using the <code>Consumer&lt;T></code> widget.</li><li>Using the <code>Provider.of&lt;T>(context)</code>.</li></ol>
<!-- /wp:list -->

```dart
late HomeViewModel viewModel;
@override
void initState() {
  viewModel = Provider.of<HomeViewModel>(context, listen: false);
  WidgetsBinding.instance.addPostFrameCallback((_) {
    viewModel.fetchData();
  });
  super.initState();
}
```

<!-- wp:paragraph -->
<p>We instantiate the <code>viewModel</code> using <strong>Provider. of </strong>inside the <code>home_view</code> </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The <code>Provider.of&lt;T&gt;(context)</code> is used when you need to access the dependency but you don’t want to make any changes to the User Interface. We simply set the <code>listen: false</code> signifying that we don’t need to listen to updates from the ChangeNotifier. The <code>listen: false</code> parameter is used to specify whenever you're using Provider to fetch an instance and call a method on that instance.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><em>Note: We can also use the below</em></p>
<!-- /wp:paragraph -->

```dart
viewModel = context.read<HomeViewModel>();
```

For reacting to the changes which happen to viewModel we use the Consumer<T> when we want to rebuild the widgets when a value changes. It is a must to provide the type <T> so that the Provider can understand which dependency you are referring to.

```dart
Consumer<HomeViewModel>(
    builder: (_, model, child) {
     // YOUR WIDGET                     
    },
    child: // SOME EXPENSIVE WIDGET
)
```

<!-- wp:paragraph -->
<p>The <a href="https://pub.dev/documentation/provider/latest/provider/Consumer-class.html" target="_blank" rel="noreferrer noopener">Consumer</a> widget doesn’t do any fancy work. It just calls <a href="https://pub.dev/documentation/provider/latest/provider/Provider/of.html" target="_blank" rel="noreferrer noopener">Provider.of</a> in a new widget, and delegates its <code>build</code> implementation to the <a href="https://pub.dev/documentation/provider/latest/provider/Consumer/builder.html" target="_blank" rel="noreferrer noopener">builder</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The Consumer widget takes two parameters, the <code>builder</code> parameter and the <code>child</code> parameter (optional). The <code>child</code> parameter is an expensive widget that does not get affected by any Change in the ChangeNotifier.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This builder can be called multiple times (such as when the provided value change) and that is where we can rebuild our UI. The Consumer widget has two main purposes:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>It allows obtaining a value from a provider when we don’t have a <a href="https://api.flutter.dev/flutter/widgets/BuildContext-class.html" rel="noreferrer noopener" target="_blank">BuildContext</a> that is a descendant of said provider, and therefore cannot use <a href="https://pub.dev/documentation/provider/latest/provider/Provider/of.html" rel="noreferrer noopener" target="_blank">Provider. of</a>.</li><li>It helps with performance optimization by providing more granular rebuilds.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Unit tests for the view model (Optional)</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can mock dependencies by creating an alternative implementation of a class by making use of the <a href="https://pub.dev/packages/mockito" rel="noreferrer noopener" target="_blank">Mockito package</a> as a shortcut.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<figure class="wp-block-image aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/0*raBWlTIpC0H5EKFM.png" alt="MVVM Architecture + Repository"/><figcaption>MVVM Architecture + Repository</figcaption></figure>
<!-- /wp:image -->

<!-- wp:heading {"level":4} -->
<h4>What are&nbsp;Services</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Services are normal Dart classes that are written to do some specialized task in your app. The purpose of a service is to isolate a task, especially third-party packages that are volatile, and hide its implementation details from the rest of the app.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Some common examples you might create a service to handle:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Using a 3rd party package, for instance, read and write to local storage (shared preferences)</li><li>Using Cloud Providers like Firebase or some other third-party package.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Let’s say you’re using <a href="https://pub.dev/packages/package_info_plus" rel="noreferrer noopener" target="_blank">package_info</a> to get the package details of your app.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You use the package directly inside the app and after some time you found an even great package. You go through and replace all the references of <code>package_info</code>with the new package <code>some_great_package</code>. This was surely <strong>a waste of your time and effort</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let’s say the product owners found, that no user was using this feature, instead, they request a new feature. You go through and remove all the references with the <code>some_great_package</code> This was again <strong>a waste of your time and effort</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The point is when you have tight coupling to some function scattered around your code, it makes it difficult and error-prone to change.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Clean coding takes upfront time and effort but will save you more time and effort in the long run</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This is where <code>services</code> come in. You make a new class and call it something like <code>PackageInfoService</code>. The rest of the classes in the app don’t know how it works internally. They just call methods on the service to get the result.</p>
<!-- /wp:paragraph -->

```dart
abstract class PackageInfoService {
  Future<String> appVersion();
}
class PackageInfoServiceImpl implements PackageInfoService {
  @override
  Future<String> appVersion() async {
    final packageInfo = await PackageInfo.fromPlatform();
    String version = packageInfo.version;
    String build = packageInfo.buildNumber;
    return 'v$version ($build)';
  }
}
```

<!-- wp:list -->
<ul><li>This makes it easy to change. If you want to switch <code>package_info</code> to a<code>some_great_package</code> just alter the code inside the service class. Updating the service code automatically affects everywhere the service is used inside the app.</li><li>Supports swapping around implementations. You can create a “fake” implementation that just returns hard-coded data, while the other team is finalizing/developing the service implementation.</li><li>Sometimes the implementation may rely on other services. For example, you <code>xyzService</code> might use a service for making a network call to get other types of data.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Register your service</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Using a service locator like GetIt is a convenient way to provide services throughout your app</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>We use the <code>locator</code> to register our <code>PackageInfoService</code></li><li>We will be registering <code>PackageInfoService</code> as a lazy singleton. It only gets initialized when it’s first used. If you want it to be initialized on app startup, then use <code>registerSingleton()</code> it instead. Since it’s a singleton, you’ll always have the same instance of your service.</li></ul>
<!-- /wp:list -->

```dart
void setupLocator() {
locator.registerLazySingleton<PackageInfoService>(() =>
PackageInfoServiceImpl());
}
```

<!-- wp:paragraph -->
<p><strong>Using the service</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Since we registered the service using the GetIt, we can get a reference to the service from anywhere in the code</p>
<!-- /wp:paragraph -->

```dart
class MyClass {
  PackageInfoService packageService = locator<PackageInfoService>();
}
```
<!-- wp:paragraph -->
<p>Then you can use it within that class like this:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><code>packageService.getSomeValue()</code></li><li><code>packageService.doSomething(someValue)</code>&nbsp;</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p><strong>Unit tests for the service (Optional)</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can mock dependencies by creating an alternative implementation of the service class by making use of the <a href="https://pub.dev/packages/mockito" rel="noreferrer noopener" target="_blank">Mockito package</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Brief:</strong></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>A <code>repository</code> is for accessing objects in a collection-like manner.</li><li>A <code>service</code> is a class with methods for executing business logic, that may coordinate various other services (such as multiple repositories) to perform a single action or get a single result.</li></ul>
<!-- /wp:list -->

{% youtube 7Q9dxzIo314 %}

<!-- wp:paragraph -->
<p><a rel="noreferrer noopener" href="https://github.com/AseemWangoo/dynamism" target="_blank"><em>Source code.</em></a>

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>