A beginner’s guide to architecting a Flutter app

Suragch
Suragch
Jan 1 · 7 min read

How to use the “stacked” package by FilledStacks

Image for post
Image for post
Beginners need a simple model to follow

If you are reading this article again for a quick refresher, scroll down to the Summary section at the bottom.

Flutter gives you a lot of freedom to do whatever you want. Sometimes that freedom can be a drawback, though, when you’re starting out. That’s certainly true for state management and app architecture.

I’m a fan of FilledStacks (Dane Mackier) and Reso Coder (Matt Rešetár) for their work in educating the Flutter community about app architecture. FilledStacks especially has designed a model of structuring apps which is accessible to beginners. The tutorials tend to be on the long side, though, and the architecture has also evolved over time. That makes it somewhat difficult for a newcomer to understand what is happening.

My goal in this article is to give you a high level understanding of how to architect you app and then some very practical guidance for doing that using the stacked package by FilledStacks.

Architecture overview

Image for post
Image for post

You create a new View Model for every screen on your app. The Services are accessible globally, though, so they stay the same. A multi-screen app would be structured something like this:

Image for post
Image for post

Practically speaking, the files might be organized something like this:

Image for post
Image for post

You are free to use a different organization, though. FilledStacks likes to put the view models in the core folder (at least in the original tutorial). I think I prefer to keep them close to the views that use them, but I usually change my mind for every new app I make. Read this article for more thoughts on this. You can change later when the need arises. All it takes is moving the files and changing the import paths.

Example

I encourage you to actually work through the example yourself rather than just reading it. This will help you to get a better grasp of the concept.

Getting started

In pubspec.yaml, add the stacked package:

dependencies:
stacked: ^1.6.0

Note: You don’t actually have to use the Stacked package to implement this architectural pattern. The advantages, though, are that it removes some boilerplate code and also hides away some of the complexities of the Provider package, which it uses internally. If you would like to get some background of how all this works under the hood, read the original FilledStacks Provider architecture tutorial and also my previous article Making sense of all those Flutter Providers.

For this example I’m not going to create the full folder structure that I showed above, but you can if you want to.

View Model

Note that the class extends ChangeNotifier, which gives you the notifyListeners() method. The view will be a listener, so this method is what the Stacked package will use to rebuild the UI whenever there are changes. ChangeNotifier is part of Flutter foundation, so we don’t actually have any dependencies on the stacked or provider packages here in the view model.

View

Paste in the following code:

At the top of the build() method you can see ViewModelBuilder. This is what provides the CounterViewModel to the widget tree. Because the state is in the view model, there is no need to use a StatefulWidget. Thus you can see that CounterScreen is a StatelessWidget. It gets the counter value from the view model. When the button is pressed this will call increment() on the view model, which in turn will also trigger a rebuild with the new counter value.

We still have to clean up main.dart. Replace it with the following code:

If you run the app now it should behave exactly like the default counter app.

Image for post
Image for post
Pushing the button increments the counter as expected

Benefits of the Provider Architecture package

Replace counter_viewmodel.dart with the following code:

You can see that now there is a method to fetch some initial data from a web API service. I’m not going to talk about making a service here, so I just included some fake code at the bottom. You can read more about creating an actual service in this article:

The magic of the Stacked package is that ViewModelBuilder has an onModelReady callback that allows you to run some initialization code when the view model is ready.

In counter_screen.dart, add the following argument to ViewModelBuilder:

onModelReady: (model) => model.loadData(),

Now when you run the app it will update automatically after the two second Future completes.

Image for post
Image for post

Summary

Dependency

Add the stacked package dependency to pubspect.yaml.

dependencies:
stacked: ^1.6.0

View Model

Create a new file called my_screen_viewmodel.dart and add a Dart class that extends ChangeNotifier:

import 'package:flutter/foundation.dart';class MyScreenViewModel extends ChangeNotifier {
int _someValue = 0;
int get someValue => _someValue;
Future loadData() async {
// do initialization...
notifyListeners();
}
void doSomething() {
// do something...
notifyListeners();
}
}

View

Create a new file called my_screen.dart and make your normal widget layout for that screen.

Add a ViewModelBuilder to the top of your MyScreen widget tree. The easiest way to do this is to use a shortcut to wrap the top widget with a new widget. Instead of having a child, though, use => to return the top widget from the builder parameter.

import 'package:stacked/stacked.dart';class MyScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ViewModelBuilder<MyScreenViewModel>.reactive(
viewModelBuilder: () => MyScreenViewModel(),
onModelReady: (model) => model.loadData(),
builder: (context, model, child) => MyTopWidget(

// your widget tree
),
);
}
}

Then within your widget tree you can access the view model like this:

  • model.someValue
  • model.doSomething()

Going on

Here are a couple more options that you may want to check out. I’ve found them to be more complex than the Stacked architecture, but they still have good things to add.

FilledStacks claims that the Provider Architecture can work for apps of any size. Though I haven’t used it in a large app myself yet, I’m confident that it will give beginning developers a strong foundation for building apps and will carry you well into the intermediate and even advanced levels.

Update

Essentially it is the same solution as what I’ve described in this article. The main difference is that the state uses immutable data rather than a ChangeNotifier, which is mutable data. So far I’m liking Riverpod.

Flutter Community

Articles and Stories from the Flutter Community

Suragch

Written by

Suragch

A Flutter and Dart developer with a background in Android and iOS. Follow me on Twitter @suragch1 or become a Patron: www.patreon.com/user?u=32145209.

Flutter Community

Articles and Stories from the Flutter Community

Suragch

Written by

Suragch

A Flutter and Dart developer with a background in Android and iOS. Follow me on Twitter @suragch1 or become a Patron: www.patreon.com/user?u=32145209.

Flutter Community

Articles and Stories from the Flutter Community

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store