ScopedModel | Score Counter App using ScopedModel way of state management in the flutter.

Ravi Shankar Singh
FlutterFly
Published in
4 min readJan 26, 2019
Score Counter App

State Management in flutter is a very hot topic and we have various way to manage the state according to the requirements. One of the state management art in flutter is using ScopedModel and in today we are going to talk about that.

Before we begin…

Let us know something about ScopedModel…

ScopedModel is a third party package that is maintained by Brian Egan and Andrew Wilson. It is a set of utilities that allow you to easily pass a data Model from a parent Widget down to its descendants and it also rebuilds all of the children that use the model when the model is updated.

The library provides three main classes :

  1. Model Class
  2. ScopedModel Widget
  3. ScopedModelDescendant Widget

We create our own classes and extends it with Model class provided by the ScopedModel package and listens for the change. If you need to pass your model deep down the Widget hierarchy you can wrap your Model in a ScopedModel widget and this will make your model available to your all descendant widgets. Then come to the ScopedModelDescendant widget is used to find the appropriate ScopedModel in the widget tree. It will automatically rebuild whenever the model notifies that some change has been made using the notifyListener() inside the model.

Now Let's begin with our Score Counter application…

Start with adding the required dependency in the pubspec.yaml file

dependencies: scoped_model: ^1.0.1

Now Click on Package get at the top reflected flutter commands or manually update by running

$ flutter packages get

Now create a separate package inside your lib folder named Model and inside that create a new dart file named score_model.dart. All the business logic part will be placed here and will update the user interface from here using the notifyListeners() call.

In our application, we are going to have two points system to award points to the respective teams. Let us start by importing the scoped_model.dart to our model class.

import 'package:scoped_model/scoped_model.dart';

Create a class ScoreModel and extend Model like this:

class ScoreModel extends Model {}

Now we will write the score incrementing part in our model using getters and setters.

class ScoreModel extends Model {
int _score = 0;

int get score => _score;

void increment3Score() {
_score += 3;
notifyListeners();
}

void increment2Score() {
_score += 2;
notifyListeners();
}
}

There are two types of points awarded to the teams one is two point and other is three points at a time. Now lets come to the main.dart file.

void main() => runApp(MyApp());class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Score Board',
theme: ThemeData.dark(),
);
}
}

We have not assigned home yet and will initialize it soon with our ScoreModel wrap in ScopedModel like this ScopedModel<ScoreModel>. Assign the model by creating a new instance of our model class i.e ScoreModel and child with the Children that we will display.

home: ScopedModel<ScoreModel>(
model: ScoreModel(),
child: ScoreCard(),
),

Now let's create our child class that will have the user interface for our application having app bar with a text “Score Board”, for now, we will give a Center widget to our body and lets create a dart file that will contain the team name, score, and two buttons to award points so that we can use it to build our Score Card.

class ScoreCard extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Score Board',
),
),
body: Center()
);
}

Create a new dart file named counter.dart inside the lib folder

class Counter extends StatelessWidget {
final String teamName;

Counter({Key key, this.teamName});

@override
Widget build(BuildContext context) {
return ScopedModelDescendant<ScoreModel>(
builder: (context, child, model) => Container(
margin: EdgeInsets.only(top: 20, bottom: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'$teamName:',
style: TextStyle(
fontSize: 40,
),
),
Text(
model.score.toString(),
style: Theme.of(context).textTheme.display1,
),
Column(
children: <Widget>[
FlatButton(
onPressed: model.increment3Score,
child: Text('+ 3 POINTS'),
color: Colors.lightBlueAccent,
splashColor: Colors.green,
),
FlatButton(
onPressed: model.increment2Score,
child: Text('+ 2 POINTS'),
color: Colors.deepOrangeAccent,
splashColor: Colors.redAccent,
),
],
)
],
),
),
);
}
}

Counter class have two Text to display the team name and their score, and two buttons that will be used to award the team points. Here in this class build method, we return a widget that wraps our Model ScoreModel in a ScopedModelDescendant Widget. Wrapping with ScopedModelDescendant rebuild the User Interface whenever the model notifies that some change has been made using the notifyListener() inside the model.

Now lets come back to our main.dart file in which we have our class ScoreCard and define a body for it.

body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
ScopedModel<ScoreModel>(
model: teamAScoreModel,
child: Counter(
teamName: "Team A",
),
),
Container(
width: 2.0,
height: MediaQuery.of(context).size.height / 2,
decoration: BoxDecoration(color: Colors.white),
),
ScopedModel<ScoreModel>(
model: teamBScoreModel,
child: Counter(
teamName: 'Team B',
),
),
],
),
),

We wrap the ScoreModel in ScopedModel here to let the model available to all our descendant widgets. It makes descendant widgets to call the getters and setters inside the model and make changes to the UI.

Final Application Demo

That's all with ScopedModel in our score counter application. You can follow the tutorial and make your own counter application using ScopedModel state management or you can just clone the repository code at GitHub.

Read my other article:

https://medium.com/devmins/flutter-custom-paint-tutorial-draw-a-custom-shape-path-in-flutter-afbbf0202941

Did I get something wrong? Mention it in the comments. I would love to improve.

If you liked what you read, please leave some claps!

Follow me:

Twitter : https://twitter.com/imRaviSSingh

Facebook : https://www.facebook.com/itsravishankarsingh

Instagram : https://www.instagram.com/itsravishankarsingh/

Github : https://github.com/ravishankarsingh1996

LinkedIn : https://www.linkedin.com/in/itsravishankarsingh/

About.me :https://about.me/itsravishankarsingh

--

--