Using Mobx in Flutter: Hot or Cold Game

Alperen Ekin
HardwareAndro
Published in
4 min readOct 22, 2020

Recently I wanted to enhance my understanding in Flutter mobx by doing simple example and here i am. In this article, I am going to explain mobx usage in the frame of MVVM architecture.

Mobx is a strong library for managing states in your application. It provides an easy management on your view pages. Mobx provides us three main operation: Observables, Actions and Reactions. We will see how to use those in our project.

Hot or Cold Game

In the game, the idea is simple you make guess and with every new guess you are trying to find the secret number. If your guess is closer than the previous guess to the secret number, you will get feedback as hot otherwise it is cold.

In the MVVM perspective, view model and mobx complete each other. Let’s start coding.

dependencies:
mobx: ^1.1.1
flutter_mobx: ^1.1.0
dev_dependencies:
flutter_test:
sdk: flutter
mobx_codegen:
build_runner:

We need mobx and flutter_mobx packages and besides that mobx_codegen and build_runner generate the .g.dart file which is needed to use features of mobx. Thanks to those packages you dont need to keep regenerate code therefore development becomes faster.

In model part enumeration type needed to determine current state of application.

enum ResultEnum{
HOT,COLD,HIT
}

Now we can focus on view model,

class HotColdViewModelStore = HotColdViewModel with _$HotColdViewModelStore;abstract class HotColdViewModel with Store,BaseViewModel{
int randomNumber;
int _difference;
int _differenceAfter = 0;
@observable
bool isVisible = false;

@observable
ResultEnum resultEnum;
}

isVisible checks if the number to guess is visible or not. Technically we let user to cheat if they are in a unlucky day. 😀

There are two variable marked as observable. That means when there action related with those variables, they will observe and update according to it.

void initRandom(){
Random random = new Random();
randomNumber = random.nextInt(100);
}

Also we need a random number to find out at the end of game so this function will set it.

@action
void changeVisibility(){
isVisible = !isVisible;
}

@action
void isHotOrCold(int guess){
_difference = guess - randomNumber;
if( _difference != 0){
if(_difference.abs() > _differenceAfter.abs()){
resultEnum = ResultEnum.COLD;
}else{
resultEnum = ResultEnum.HOT;
}
}else{
resultEnum = ResultEnum.HIT;
}
_differenceAfter = _difference;
myController.text = "";
}

There are also two action functions that have observable variables in a part of body. First function controlls visibility of random number in screen.

The second function is where we decide if the guess is hot or cold. Shortly we take the user guess, check its difference with random number and store that difference, when there is new guess arrive we compare it with previous difference and decide if it is hot or cold.

After that we can generate our code with build runner.

flutter packages pub run build_runner watch

As we include some code under Store(that we used in view model class) it will generate code automatically.

.g.dart file has generated.

The view model is ready to use 👌🏻

Using Observables and Actions in View

In order to track the changes in variables, while showing them in screen we should wrap them with Observer widget.

StandardRaisedButton makeGuessButton() {
return StandardRaisedButton(
color: Colors.blue.shade200,
onPressed: () {
viewModel.isHotOrCold(int.parse(viewModel.myController.text));
},
child: Text(
LocaleKeys.view_send.tr(),
textScaleFactor: context.fixScaleFactor,
),
);
}
Observer greenObserver() {
return Observer(builder: (context) {
return Container(
width: dynamicWidth(0.2),
height: dynamicHeight(0.15),
child: Icon(Icons.done),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(context.borderRadius),
color: viewModel.resultEnum == ResultEnum.HIT
? Colors.green
: Colors.grey),
);
});
}

Observer coldObserver() {
return Observer(builder: (context) {
return Container(
width: dynamicWidth(0.2),
height: dynamicHeight(0.15),
child: Icon(Icons.ac_unit),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(context.borderRadius),
color: viewModel.resultEnum == ResultEnum.COLD
? Colors.blue
: Colors.grey),
);
});
}

Observer hotObserver() {
return Observer(builder: (context) {
return Container(
width: dynamicWidth(0.2),
height: dynamicHeight(0.15),
child: Icon(Icons.wb_sunny),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(context.borderRadius),
color: viewModel.resultEnum == ResultEnum.HOT
? Colors.red
: Colors.grey),
);
});
}

Container colors indicate that if the guess is cold,hot or hit. After every guess isHotOrCold function triggered and this ended up with a change in resultEnum variable which let container to change color.

StandardRaisedButton cheatRaisedButton() {
return StandardRaisedButton(
color: Colors.blue.shade200,
onPressed: () {
viewModel.changeVisibility();
},
child: Observer(builder: (context) {
return viewModel.isVisible
? Text(
LocaleKeys.view_hide.tr(),
textScaleFactor: context.fixScaleFactor,
)
: Text(
LocaleKeys.view_show.tr(),
textScaleFactor: context.fixScaleFactor,
);
}));
}

Observer randomShower() {
return Observer(builder: (context) {
return Visibility(
visible: viewModel.isVisible,
child: Text(
viewModel.randomNumber.toString(),
textScaleFactor: context.fixScaleFactor,
));
});
}

Similar scenario valid for visibility, once changeVisibility is triggered, the isVisible variable changes and since it is wrapped with Observer, we can observe this changing and use it in program.

At the end the behaviour is as expected. As you can see , I didn’t need to use setState in program. I believe Mobx and MVVM have strong usage together.

I tried to explain basics of mobx in this article, I hope I could be helpful for understanding of Mobx in flutter. In the project, I also applied basic localization and simple push notification. You can also reach those and full code from the link below.

Thanks for reading, I am open for feedbacks. See you in the next articles!

--

--