Let’s take a look at our Todo list. We were working to calculate and show the score. We’ve successfully wrapped up that task.
Our next task, is a start over button so the user can play multiple rounds.
Ok, When writing code, especially user interface code, you’ll often times be employing something called a callback. A callback looks just like another variable, but instead of holding a value, it holds the method of another object.
This is a great way for objects to communicate with each. Lets take two objects.
One object is a chat user interface object and the other is the network object. The chat object wants to print out a list of recent messages from the people who are logged in so it asks the network object to get those names.
Except, the network object has no idea how long it will take. It could be just a second or maybe thirty or forty seconds depending on the connection.
Instead of waiting, the chat object passes in a method to the network object. That way, the chat object can read Cat Fancy instead of just waiting for the network object. When the network object is done, it calls chat’s callback method.
There are lots of different callbacks. We’ll be using the void callback. This is method that doesn’t return a value.
To get started, open your project in progress or download the starter project for this episode. We want to provide a way to start over the game. We already have a start over button.
Open score.dart. We will want to define a callback so that when the user taps the start over button, our callback will be called. First, let’s define a callback property.
final VoidCallback onStartOver;
We’re getting an error because we haven’t updated our constructor to include onStartOver as one of the argument. Update the constructor to the following:
const Score(
{Key? key,
required this.totalScore,
required this.round,
required this.onStartOver})
: super(key: key);
Now we want call our callback. Scroll down to the start over button and add the following in onPressed:
TextButton(
child: const Text('Start Over'),
onPressed: () {
onStartOver();
},
),
Now we’re getting a compile error. This is because our Score now requires a callback so we have to pass one to the widget. Open up main.dart.
When we start over, we will need to produce a new target value. Mind, we also need to create a new target value when the game is created. We could copy the line in two places but are you starting to smell something from the code?
Instead of adding code smell, let’s do a little reorganizing otherwise known as refactoring.
First, we’ll create a new property in _GamePageStateState to generate a new target value.
int _newTargetValue() => Random().nextInt(100) + 1;
Now lets update our initState to use our property.
@override
void initState() {
super.initState();
_model = GameModel(_newTargetValue());
}
Let’s also update the SetState property in _showAlert to use it as well.
setState(() {
_model.totalScore += _pointsForCurrentRound();
_model.target =_newTargetValue();
_model.round += 1;
});
Now let’s create our callback method. Remember, since we defined the our callback as a void callback, this callback method can’t return a value. We’ll call it startNewGame and make it private.
void _startNewGame() {
}
We want to update our widget by calling setState.
setState(() {
});
After which, we can reset all the fields.
_model.totalScore = GameModel.scoreStart;
_model.round = GameModel.roundStart;
_model.current = GameModel.sliderStart;
_model.target = _newTargetValue();
Okay, we’ve setup our callback and we are all good to go. We just have to pass it into our score widget. Simply do this in the constructor.
Score(
totalScore: _model.totalScore,
round: _model.round,
onStartOver: _startNewGame)
And that’s it - we now have a working start over button. Now run your app and play a few rounds. When you are ready, click the start over button and look at that - the game starts over!