DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Exploring Exciting New Features in Java 17 With Examples
  • A Data-Driven Approach to Application Modernization
  • JSON-Based Serialized LOB Pattern
  • Serverless Patterns: Web

Trending

  • Comprehensive Guide to Property-Based Testing in Go: Principles and Implementation
  • Blue Skies Ahead: An AI Case Study on LLM Use for a Graph Theory Related Application
  • DGS GraphQL and Spring Boot
  • Unlocking AI Coding Assistants: Generate Unit Tests
  1. DZone
  2. Data Engineering
  3. Data
  4. A Beginner’s Guide To Implementing MVVM Architecture In Flutter

A Beginner’s Guide To Implementing MVVM Architecture In Flutter

Model View ViewModel (MVVM) is the industry-recognized software architecture pattern that overcomes all drawbacks of MVP and MVC design patterns.

By 
Brijesh Patel user avatar
Brijesh Patel
·
Dec. 05, 21 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
6.4K Views

Join the DZone community and get the full member experience.

Join For Free

There was a time in the tech space, where businesses and companies struggled to develop an app for their idea. This was primarily because they had to develop the same idea twice as applications – one for the Android ecosystem another one for the iOS ecosystem.

Financially and logistically, this was straining as companies had to hire two dedicated teams to work on the app development process or increase their time to market by hiring one team and waiting until one of the applications got developed for the other one to start.

All of this changed in May 2017, when Google rolled out a revolutionary language that allowed developers to develop an app just once and use it across multiple platforms. That platform is what we call Flutter and Flutter application development has been a fan favorite among the developer community.

Though there are tons of features to rave about with Flutter application development, what appears to be the most prominent feature is its MVVM architecture.

As an experienced developer at a mobile application developing company, I have penned this article to briefly look at the model and understand how to implement MVVM architecture in Flutter.

What Is MVVM Architecture?

The MVVM pattern provides the distribution of data and UI which gives benefits such as flexibility and reusability of the code as well as data.

MVVM stands for Model, View, and View Model. The design pattern of MVVM is to build a view model that can represent the data through a view.

MVVM and Architecture

MVVM Diagram


In the above diagram of MVVM, you could see that the view model occupies the central position, which sends and receives data from the model and provides data to the view. It observes the changes in the data and responds accordingly using the model to the view.

The Model

The Model in the MVVM presents real-time data that will be used in application development. The Model only reflects the actual data and not the characteristics or any feature related to the application.

It means you can’t manipulate the way the data will be represented or formatted. Each item in the dataset will be presenting its own model when the data is fetched. The main Model is kept away from the logic part for neat code but sometimes, it includes the validation logic as well.

The View

The View in the MVVM design pattern presents the user interacting with the application. The View is a set of libraries to present the data more accurately and appropriately.

The View possesses the property to utilize behaviors associated with the Model such as identifying and acting according to user input. The View handles the actions done by a user, which can be manipulated by the Model’s functionalities.

The View Model

The most essential element of MVVM architecture is that the View Model occupies a central position that sends and receives the data from the model and provides the data to the View. Besides, it also observes the data changes and responds accordingly using the model to the view.

The View Model holds the actual data and the View part holds the formatted or updated data while keeping the controller as an interface between them.


Essential elements of MVVM architecture

MVVM Implementation

MVV implementation is simple. All you have to do is follow the steps below:

  • Create a new project.
  • Get dependencies
  • Create the model.
  • Create UI.
  • Create a web service.
  • Create a view model.
  • Create a widget.
  • Create main.dart.

Create a New Project

Create a new Flutter app. Create a New mvvm_example and remove all the code as we will add a custom main.dart.

Get Dependencies

Add the latest version of HTTP/dio and Provider package under the dependencies in pubspec.yaml file.

1
2
3
4
5

dependencies:

 

 dio: ^4.0.0

 provider: ^5.0.0

 cached_network_image: ^3.0.0


Note: Use the latest dependencies version.

Create the Model

We will be building the latest News Article app, where the model will be the NewsArticle. In your “lib” folder, create a new folder and name its models. Inside the model folder, create a dart file and name it “NewsArticle.dart”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

class NewsArticle {

 String author;

 String title;

 String description;

 String url;

 String urlToImage;

 String publishedAt;

 String content;

 

 NewsArticle(

     {this.author,

     this.title,

     this.description,

     this.url,

     this.urlToImage,

     this.publishedAt,

     this.content});

 

 NewsArticle.fromJson(Map<String, dynamic> json) {

   author = json['author'];

   title = json['title'];

   description = json['description'];

   url = json['url'];

   urlToImage = json['urlToImage'];

   publishedAt = json['publishedAt'];

   content = json['content'];

 }

}

 

 


Create UI

Create a new folder in your lib folder and name it “screens.” Create a “dart” file and name it “NewsScreen.dart”. Enter the following code in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

import 'package:demo_mvvm/viewmodels/news_article_list_view_model.dart';

import 'package:demo_mvvm/widgets/news_grid.dart';

import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

 

 

class NewsScreen extends StatefulWidget {

 @override

 _NewsScreenState createState() => _NewsScreenState();

}

 

class _NewsScreenState extends State<NewsScreen> {

 @override

 void initState() {

   super.initState();

   Provider.of<NewArticleListViewModel>(context, listen: false).topHeadlines();

 }

 

 @override

 Widget build(BuildContext context) {

   var listviewModel = Provider.of<NewArticleListViewModel>(context);

   return Scaffold(

     appBar: AppBar(

       title: Text('Top News HeadLine'),

     ),

     body: NewsGrid(articles: listviewModel.article),

   );

 }

}

 

 


Create a Web Service

Create a new folder in your lib folder and name it “services.” Create a “dart” file and name it “WebServices.dart”. For the web service, we will use an API endpoint to newsapi.org.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

import 'package:dio/dio.dart';

import '../models/news_article.dart';

 

class WebServices {

 var dio = new Dio();

 

 Future<List<NewsArticle>> fetchTopHeadLines() async {

   String baseUrl =

       "https://newsapi.org/v2/top-headlines?country=in&apiKey=9e72a381576143e48ff8c07b8d2026f4";

 

   final response = await dio.get(baseUrl);

 

   if (response.statusCode == 200) {

     final result = response.data;

     Iterable list = result['articles'];

     return list.map((article) => NewsArticle.fromJson(article)).toList();

   } else {

     throw Exception("Failed to get top new");

   }

 }

}

 


Create a View Model

In your “lib” folder, create another folder and name it “viewmodels”. In this folder, we will create two files:  one will be the “NewsArticleViewModel,” which will have the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

import '../models/news_article.dart';

 

class NewsArticleViewModel {

 NewsArticle _newsArticle;

 

 NewsArticleViewModel({NewsArticle article}) : _newsArticle = article;

 

 String get title {

   return _newsArticle.title;

 }

 

 String get author {

   return _newsArticle.author;

 }

 

 String get description {

   return _newsArticle.description;

 }

 

 String get url {

   return _newsArticle.url;

 }

 

 String get urlToImage {

   return _newsArticle.urlToImage;

 }

 

 String get publishedAt {

   return _newsArticle.publishedAt;

 }

 

 String get content {

   return _newsArticle.content;

 }

}

 

 


Create a new class called “NewsArticleViewModel” that will take in the model “NewsArticle” as a parameter and return the values from that model inside the View Model.

The next file will be NewArticleListViewModel” and will have the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

import 'package:demo_mvvm/models/news_article.dart';

import 'package:demo_mvvm/services/web_services.dart';

import 'package:demo_mvvm/viewmodels/news_article_news_model.dart';

import 'package:flutter/material.dart';

 

enum LoadingStatus { completed, searching, empty }

 

class NewArticleListViewModel with ChangeNotifier {

 LoadingStatus loadingStatus = LoadingStatus.empty;

 List<NewsArticleViewModel> article;

 

 void topHeadlines() async {

   List<NewsArticle> newsArticle = await WebServices().fetchTopHeadLines();

   loadingStatus = LoadingStatus.searching;

   notifyListeners();

 

   this.article = newsArticle

       .map((article) => NewsArticleViewModel(article: article))

       .toList();

 

   if (article.isEmpty) {

     loadingStatus = LoadingStatus.empty;

   } else {

     loadingStatus = LoadingStatus.completed;

   }

 

   notifyListeners();

 }

}

 

 


Create a Widget.

Widget creator will be inside a new folder. We will create a widget in the “lib” folder. Inside this folder, create a file and name it “NewsGrid.dart”. This is just to continue with the MVVM reusability of the code. Here is the code for it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

import 'package:cached_network_image/cached_network_image.dart';

import 'package:demo_mvvm/viewmodels/news_article_news_model.dart';

import 'package:flutter/cupertino.dart';

import 'package:flutter/material.dart';

 

class NewsGrid extends StatelessWidget {

 final List<NewsArticleViewModel> articles;

 

 NewsGrid({this.articles});

 

 @override

 Widget build(BuildContext context) {

   return GridView.builder(

     gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(

       crossAxisCount: 2,

     ),

     itemBuilder: (context, index) {

       var article = this.articles[index];

       return GridTile(

         child: Container(

           child: CachedNetworkImage(

             imageUrl: article.urlToImage,

             imageBuilder: (context, imageProvider) {

               return Container(

             

    margin: EdgeInsets.symmetric(horizontal: 10, vertical: 20),

                 decoration: BoxDecoration(

                   borderRadius: BorderRadius.circular(25),

                   image: DecorationImage(

                     image: imageProvider,

                     fit: BoxFit.cover,

                   ),

                 ),

               );

             },

             placeholder: (context, url) {

               return Center(

                 child: CircularProgressIndicator(),

               );

            

 },

             errorWidget: (context, url, error) {

               return Container(

                 child: Center(

                   child: Text(

                     'No Image Found',

                     style: TextStyle(fontWeight: FontWeight.bold),

                   ),

                 ),

               );

             },

           ),

         ),

         footer: Container(

           padding: EdgeInsets.symmetric(horizontal: 15),

           child: Text(

             article.title,

             style: TextStyle(fontWeight: FontWeight.bold),

             maxLines: 1,

           ),

         ),

       );

     },

     itemCount: this.articles.length,

   );

 }

}

 


Create main.dart

Finally, we will create the main.dart file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

import 'package:demo_mvvm/screens/news_screen.dart';

import 'package:demo_mvvm/viewmodels/news_article_list_view_model.dart';

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import 'package:flutter/services.dart';

 

void main() {

 SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(

     statusBarColor: Colors.blue, statusBarBrightness: Brightness.light));

 runApp(MyApp());

}

 

class MyApp extends StatelessWidget {

 // This widget is the root of your application.

 @override

 Widget build(BuildContext context) {

   return MaterialApp(

     debugShowCheckedModeBanner: false,

     title: 'Flutter Demo',

     theme: ThemeData(

       primarySwatch: Colors.blue,

     ),

   

     home: MultiProvider(

       providers: [

         ChangeNotifierProvider(

           create: (_) => NewArticleListViewModel(),

         )

       ],

       child: NewsScreen(),

     ),

   );

 }

}

 


ChangeNotifierProvider is defined to listen to a ChangeNotifier to expose the instance to its rebuild dependents whenever ChangeNotifier.notifyListeners is called. The NewsArticleViewModel(data) is of type NewsArticle, an instance of which will be provided at the top-level widget in main.dart

The parent widget is wrapped in ChangeNotifierProvider with the datatype of the ChangeNotifier NewsArticleViewModel (Data) class. This includes a builder method that returns an instance of the ChangeNotifier ‘NewsArticleViewModel(data)’ class, which is used to expose the instance to all the children.

Wrapping Up

So, this is how you implement MVVM architecture in Flutter. Flutter mobile application development is seamless when you take a systematic approach. 

I hope this post was resourceful to you!

Flutter (software) Architecture mobile app Data (computing) View model Strings Data Types

Published at DZone with permission of Brijesh Patel. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Exploring Exciting New Features in Java 17 With Examples
  • A Data-Driven Approach to Application Modernization
  • JSON-Based Serialized LOB Pattern
  • Serverless Patterns: Web

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!