An Introduction to MVVM in Flutter

In this piece, we’ll use the MVVM design pattern to write a complete Flutter application

Mohammad Azam
Dec 9, 2019 · 5 min read
Photo by Duy Huong on Unsplash

Flutter is a cross-platform framework that allows you to write iOS and Android apps using a single codebase.

By default, Flutter apps don’t use any specific design pattern. This means the developer is in charge of choosing and implementing a pattern that fits their needs. The declarative nature of Flutter makes it an ideal candidate for the MVVM design pattern.

Understanding MVVM

The MVVM design pattern originated from Microsoft. MVVM was heavily used in writing Windows Presentation Foundation (WPF) applications. The MVVM pattern is a fancy name for the PresentationModel.

Since design patterns are platform-agnostic, it can be used with any framework, including Flutter.

In this piece, we’ll create a movies app, which will fetch the movies based on an entered keyword and display them to the user. This app will be created based on the MVVM principles. Before diving into the code, check out the animation below to get an idea of the app we’ll be building.

Movies spp

Implementing the web service

Now that you’ve registered with the OMDb service and have received your key, we can move on to implementing the web service/client. The web service uses the HTTP package to make a network request and to download the JSON response, but feel free to use any networking package you want.

After JSON has been download, it’s fed to the movie model to get a list of movie objects, as shown below:

The movie model is implemented below:

Movie simply consists of a title and a poster. It also exposes a fromJson function, which allows us to create a Movie object based on the JSON response.

We used the term model to define our Movie objects, but, in reality, they’re serving the purpose of data transfer objects (DTO).

At this point, we have all the required data, and the next step is to display it on the screen. Before moving to the user interface, we must create view models that’ll be responsible for providing the data to the view.

Implementing view models

One view model, MoviesListViewModel, will represent the entire screen of displaying the movies. The second view model, MovieViewModel, will represent an individual movie — which will be displayed in the view.

The implementation of the view models is shown below:

The MovieListViewModel consists of the movies property, which is going to return a list of MovieViewModel objects. The MovieViewModel takes in a Movie object and returns the title and poster as readonly properties. The next step is to fetch movies using the web service.

Setting up ChangeNotifier and ChangeNotifierProvider

The implementation is shown below:

We have updated our MovieListViewModel to inherit from ChangeNotifier. ChangeNotifier allows us to publish change notifications, which can be used by the view to update itself.

After we fetch the movies using the web service, we call the notifyListeners function, notifying all the subscribers/listeners. At present, there is no one listening, so no one is notified the movies have been downloaded.

In order to notify the view with the updated MovieListViewModel, we’ll have to use the ChangeNotifierProvider, which is part of the Provider package. Add the provider package by adding the dependency in the pubspec.yaml file, as shown below:

Next, we need to find a good place to inject the value from the provider. The value we’re talking about is an instance of MovieListViewModel since it extends ChangeNotifier and publishes notifications to the listeners.

In our case, we can use the main.dart file and inject the value to the MovieListPage. This means the MovieListViewModel will be available to MovieListPage and all of its children.

Awesome. The final step is to display the data on the screen. This is covered in the next section.

Displaying movies

fetchMovies will fetch all the movies based on the keyword and trigger notifyListeners. In order to get an updated instance of MovieListViewModel, we’ll get help from the provider package, as shown below:

@override Widget build(BuildContext context) { 
final vm = Provider.of<MovieListViewModel>(context);

By adding the Provider inside the build method, we ensure whenever notifyListener is fired, we have access to the instance of MovieListViewModel.

Now if you run your app, it’ll fetch the movies based on the keyword and display them on the user interface.

If you want to perform an initial fetch when the page is loaded, then you can update your StatelessWidget to StatefulWidget and call fetchMovies from inside the initState method, as shown below:

Note that we’re passing listen: false for the Provider, which means this is a one-time call only, and the changes won’t be tracked by the Provider.

View the GitHub repo here.

Thanks for reading!

Better Programming

Advice for programmers.

Mohammad Azam

Written by

iOS Developer, speaker and educator. Top Udemy and LinkedIn instructor. Lead instructor at DigitalCrafts.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade