Flutter Project Organization Guide

This documentation is a guide for creating any flutter project in SGS, all the principles or guidelines must be adhered to, in attaining to the professional standard of a project set up.

You must know how to use GetX library and Dio for API calls using GetxServices controller.

File Structure description

Flutter project SGS must strictly adhere to the pattern as contained in the repository.

Assets

This folder is created as a root folder, the same level with the lib folder.

This houses all the assets like images, svg etc.

Note: the assets folder contains the below sub-folders.

Images:

This is where you store your images e.g (.png, .jpeg, .jpg, .gif etc), with a conventional naming pattern.

SVG:

Images with SVG extension, you should store them in this folder, for it is clearer to store SVG images separately.

Icon:

This folder holds your project icon. That’s the launcher app icon. And it must be saved with “icon.png”.

lottie :

Lottie animation should be in the assets folder not as a sub-folder.

Lib

Inside this folder, we have sub-folders as listed in the repository. Main.dart file comes by default.

The lib folder serves as the coding base of your projects. All the codes take place in any of these folders or files.

Main.dart

This is the main and primary file of your flutter app. Note this file must be of a stateless widget(Conventionally), most people use a stateful widget, but the best practice is to use a stateless widget.

You need to describe your theme here and must be of a GetmaterialApp widget referencing a Splash screen another file.

APP folder:

This folder contains five folders, which are:

Models

Models for your database should be described here. An example is user_model.dart

Module:

Is a folder containing all the screens created in this project. If you want to create a screen or a file, you use “get create page:the_name_the screen_you_want_to_create”. Note that there should not be any space, if not you will get an error.

While naming your page, avoid using flutter keywords of classes, to avoid issues. Example creating a page name “tab” will have an issue in the controller file, the system assumes that you are referencing a flutter class called tab controller.
Each screen comes with three folders:

Bindings folder: This is where you bind your views with your controller.

Controllers: This where you define the dependency injection of any of the screens.

Service: The service folder is where all api calls and other services dedicated to a module are housed.

Views: this serves as the normal flutter file with stateless widget where you define your screen or view.
E.g. an home screen has the following:

Route:

This is where you define the navigation within the whole project, while navigating through a screen use the GetX pattern checkout this: Click here to check the navigation section.
This route contains two main files:

The first is where your new screen you created with “get create page:the_name_the screen_you_want_to_create” is routed. Is done automatically if you use terminal or the command above.
The second one is where you define the string route name of each screen.

Services: This folder houses the base Api(which utilizes GetxServices), Database and other services in a project. Note that all the api calls must follow Dio pattern. Other services include the use of firebase etc.

Utils:

This folder includes all files made up of Custom reusable classes that contain functions and constant variables that would be utilized by the developer severally throughout the application for specific needs.

Widget:

All your custom widgets like buttons, text fields, and containers should be defined globally in this folder.Some of the listed widgets include button, footer, header, text_fields. Each project must have a primary button or even secondary button as the case maybe.

All the common widget must be defined, for example, the header, footer or the navigation for all to be able to access it.

File Naming

The first letter must start with a small letter, separated with an under-score (_), the name of the file exceeds one word. The next first letter of the word must start with a small letter.

Each file name must tally with the name of the screen or widget of the file’s functionality.

On each file or creating a screen, the class name must start with a capital letter, with Screen attached to it, and Widget attached to the widget name for the widget. eg.

“HomeScreen” is the name of the home screen file.

“ButtonWidget” is the name of the Button Widget described.

Testing

There are 3 major tests in flutter, we dwell majorly on integration test reason being that widget tests is done while performing integration tests and unit test is already handled by our backend developers but unit test can still be done:

Unit Testing

  • Make sure you have the test or flutter_test dependency(packages) added.
  • Combine multiple tests in a group.
  • Use the mockito package when dealing with classes that rely on live web services and databases.

Integration Testing

  1. Make sure you have the test or flutter_test and the flutter_driver dependency(packages) added.
  2. Create a directory named test_driver then create two files, one for the instrumented version of your app and the second for the test suite.
  3. Make sure the name of each file corresponds i.e if the instrumented app file is named app.dart the test suite file should be named app_test.dart.

General

  1. Use relative imports for files in lib:

// Don’t

import ‘package:demo/src/utils/dialog_utils.dart’;

// Do

import ‘../../../utils/dialog_utils.dart’;

2. Avoid large trees, split your code into small widgets instead
Dividing your code into small reusable widgets not only promotes its reusability, but also a clean code base that enhances readability.

3. Use widgets instead of _buildXXX (methods) to build UI elements
It is recommended to use Widgets instead of functions to build some UI elements, this is great for code reusability. Obviously you can use these “_buildXXX” methods, but only in the same tree.

4. Widgets choice matters
Always remember to check if a native widget does not exist to achieve a shape you want to reproduce. A bad choice of widgets can lead to a too large tree and a lot of useless code.

5. Dealing with APIs
To display data coming from an endpoint FutureBuilder widget is recommended. Avoid building the widget tree first, making the API call, then when these data are available, then the widget tree is refreshed with the data.

6. Use packages only when necessary
Don’t use packages to do some tasks you can manually do, unless you don’t have enough time. These packages, although they are very useful, they come with a bunch of code you don’t need.

7. Dealing with lists
Use the default constructor ListView for rendering a small list; for longer lists, use the ListView.builder constructor which renders list elements as users scroll to them.

8. Specify types for class member
Always specify the type of member when it’s value type is known. Avoid using var when possible.

9. Don’t explicitly initialize variables null
In Dart, the variable is automatically initialized to null when its value is not specified, so adding null is redundant and unneeded.

10. Use if condition instead of conditional expression
Many times we need to render a widget based on some condition in Row and Column. If the conditional expression returns null in any case then we should use if condition only.

11. Use Const in Widgets
You can cache parts of your widget tree by using const to prevent unnecessary rebuilds thereby improving performance.

12. Some widgets that might lead to performance issues include:
Opacity, Chip, ColorFilter, and ShaderMask.
For animations, you can use the AnimatedOpacity widget. The problem encountered when using the Opacity widget for animations is that it causes the widget and it’s subtree to rebuild each frame. This can be quite costly, especially when you have a large widget tree.

13. Remove Unused Resources
Especially when you’re ready to publish your application, you’ll need to remove resources that you aren’t using in your application. These could be image assets, for example. Removing unused resources and compressing images will help you reduce the size of your application.

--

--

Special Man Solution

We build software that people love by employing the best global techniques and standards. Say hello at support@specialmansolution.com