The perfect flutter boiler plate and state management solution does not exi….
Abdullah Shahid
Posted on March 8, 2023
Yo, yo, yo, 148–3 to the 3 to the 6 to the 9, representing the FLUTTER. What’s up?!
As you may know, flutter is the new sexy in mobile app development.
Flutter is an open-source mobile application development framework created by Google. It allows developers to build high-performance, cross-platform apps for both Android and iOS platforms using a single codebase. Flutter draws its own canvas using graphics engine called Skia. Unlike, React Native, which relies on native components to draw the UI.
“The choice of framework ultimately depends on the requirements and goals of the project. There is no one-size-fits-all solution, and developers must consider the trade-offs and benefits of each option before making a decision and going all in.”
It’s very true that many developers focus on making sure their code simply works, but writing high-quality production-level code requires attention to a variety of factors beyond basic functionality. This includes considerations such as scalability, readability, modularity, and adherence to good design patterns.
I have used the MVVM design pattern. I follow a service-oriented architecture, where each view has a view model and view model can call appropriate service method for API calls and to connect to outer world.
Here is the forgot password view,
import 'package:boiler_plate/ui/common/ui_helpers.dart';
import 'package:boiler_plate/ui/dumb_widgets/circular_progress_indicator.dart';
import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked/stacked_annotations.dart';
import 'forgot_view.form.dart';
import 'forgot_viewmodel.dart';
@FormView(
fields: [
FormTextField(
name: 'email',
),
],
)
class ForgotView extends StackedView<ForgotViewModel> with $ForgotView {
ForgotView({Key? key}) : super(key: key);
@override
Widget builder(
BuildContext context,
ForgotViewModel viewModel,
Widget? child,
) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: Theme.of(context).colorScheme.onBackground,
),
),
padding: const EdgeInsets.all(16),
child: const Icon(Icons.fingerprint),
),
verticalSpaceMedium,
Text(
'Forgot Password',
style: Theme.of(context).textTheme.headlineSmall,
),
verticalSpaceMedium,
Text(
'No worries, we got you covered.',
style: Theme.of(context).textTheme.bodyMedium,
),
verticalSpaceMedium,
TextFormField(
decoration: const InputDecoration(
hintText: 'Email',
prefixIcon: Icon(
Icons.email,
),
),
enableSuggestions: false,
autocorrect: false,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
controller: emailController,
),
verticalSpaceMedium,
viewModel.isBusy
? const Center(
child: MyCircularProgressIndicator(),
)
: Center(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(128, 48),
),
onPressed: () {},
child: const Text('Reset Password'),
),
),
verticalSpaceMedium,
Center(
child: TextButton(
onPressed: viewModel.navigateToLogin,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: const [
Icon(
Icons.arrow_back_ios,
),
horizontalSpaceSmall,
Text(
'Back to Login',
),
],
),
),
),
],
),
),
),
);
}
@override
ForgotViewModel viewModelBuilder(
BuildContext context,
) =>
ForgotViewModel();
@override
void onViewModelReady(ForgotViewModel viewModel) {
syncFormWithViewModel(viewModel);
}
@override
void onDispose(ForgotViewModel viewModel) {
super.onDispose(viewModel);
disposeForm();
}
}
and it’s respective forgot view model
import 'package:boiler_plate/app/app.locator.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
class ForgotViewModel extends FormViewModel {
final _navigationService = locator<NavigationService>();
void navigateToLogin() {
_navigationService.back();
}
}
Here is the output
Enough Talk. Let’s share some resources for you to have a look at.
Let me introduce Stacked. It provides a simple and elegant state management solution along with its custom without build context navigation, dialog, bottom sheet and snackbar services.
(read detailed documentation here)
Here is the repository to better understand and a very good README waiting for you to start. (Please like 👍 the repo).
What’s next? It was all I had to share and it’s time for you guys to do something creative with your next mobile app.
Oh, Also. Don’t forget to hit like 👍 if you find this article useful (It helps me a lot to share valuable info with you) and comment if you have any suggestions.
You can connect with me on LinkedIn or follow me on Medium for more.
Posted on March 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.