A sample flutter app using Injection, routing and simple authentication follows clean code and best practices
- Cleaned flutter project
- Used linter with rules as errors
- Configured route generator
- Pass parameters / variables through routes
- Simple AuthService & configured Guard for routes
- Well structured flutter project contains Screens, Components, Services and so on..
dependencies
dev_dependencies
The project root folder is src
. In order to take advantage of VS Code settings open src
as your work folder.
Auto generated files are committed into this repository. if you changed any part of codes which used auto generators you will have a compilation error. This can be resolved by running the auto generation command to create the sources necessary again to compile the app.
After checking out the branch simply run:
flutter pub run build_runner build --delete-conflicting-outputs
You can also use the watch
command to constantly generate files on change:
flutter pub run build_runner watch --delete-conflicting-outputs
Dependency injection is done by using Injectable package.
After you run the build_runner
command a file named
setup.config.dart
will get generated which holds all the injections.
Routing is done by using AutoRoute package.
There is a service called router
in /Services
which using AutoRoute package to generate routes and paths in app.
After you run the build_runner
command a file named
router.gr.dart
will get generated which holds all the routes and classes used for routing.
also for showcasing how to pass parameters from paths to screens, see /home/message/message_screen_v.dart
Selected state management for this project is Cubit
.
The Cubit is a subset of the famous implementation of BLoC Pattern: bloclibrary.dev, it abandons the concept of Events and simplifies the way of emitting states.
There are 3 parts for each component / screen to managing the states.
-
name
_m.dart- Model: this file contains definition of models for state management. to reduce duplicate codes like
copyWith
,isA[Class]
and so on, I used Freezed package to auto generate needed classes and constructors for each state model.
- each model extends from BaseState class.
- Model: this file contains definition of models for state management. to reduce duplicate codes like
-
name
_v.dart- View: this file contains the view for our component / screen which extends from BaseView class. the
BaseView
class itself extends fromStatelessWidget
and has a getter to get the viewModel inside the view. it's usinglocateService<T>()
and Injectable DI.
- View: this file contains the view for our component / screen which extends from BaseView class. the
-
name
_vm.dart- ViewModel: this file contains the viewModel for our component / screen which extends from BaseViewModel class (T is the state Model class). the
BaseViewModel<T>
class itself extends fromcubit<T>
.
- ViewModel: this file contains the viewModel for our component / screen which extends from BaseViewModel class (T is the state Model class). the
I defined 3 screens in this project.
- Home
- the root path of application.
- have a link to
message
screen with passing a parameter to it. - using
AuthService
to logout user. - showing
counter
component in it.
- have a link to
- the root path of application.
- message
- a screen to demo how to get a parameter in our routing system.
- the input parameter is defined in view's constructor [
String message
]. - also in the routing service, I have to define the input parameter for this screen.
- the input parameter is defined in view's constructor [
- a screen to demo how to get a parameter in our routing system.
- login
- login screen with a simple button and use
AuthService
to do the fake login in application.- there is optional parameter called
redirectPath
which used by router to navigate user back to where he/she been after successful login. - to guard selected routes and navigate user to this screen, I defined class
AuthenticatedUser
in the routing service class.
- there is optional parameter called
- login screen with a simple button and use
there is a file in each folder with
folder_name.dart
pattern name, which includes exports of files inside that folder. I use this pattern to minimize imports for other parts of application and classes. in usage we only need to importcomponents.dart
orscreens.dart
to use each folders implementations.
Right now there is only one component in this project to demonstrate how to use components in screens.
- counter
- a simple counter component with cubit state management.
- I used this component inside the
Home
screen.
if you have any question or suggestion, please contact me :