Flutter π¦
Project Structure
Generally speaking, a Flutter application can include multi-platforms codebase structure as a cross-platform framework. So itβs important to follow the corresponding project structure when it comes to a specific platform, for instance:
The following structure and directories must be followed for the core Flutter directories (lib/
):
project-flutter
ββ android/
ββ ios/
ββ web/
ββ assets/
ββ lib/
β ββ di/
β ββ api/
β ββ l10n/
β ββ helpers/
β ββ models/
β ββ presenters/
β ββ repositories/
β ββ preferences/
β ββ usecases/
β ββ views/
β ββ main.dart
β ββ app.dart
ββ integration_test/
ββ test/
ββ pubspec.yaml
-
assets
: static assets (images, videos, fontsβ¦) included for the application to use at the compile time. -
android/
,ios/
,web/
: contains all the platform-specific configurations corresponding to Android, iOS, and web compilation. -
lib
: the core domain logic and presentation for the whole Flutter application. Depending on the choice of architecture, there could be more or fewer presenter directories added. -
integration_test
: contains all the integration test suites. -
test
: contains all the unit test suites. -
pubspec.yaml
: specifies dependencies that the project requires, such as particular packages (and their versions), fonts, or assets files (images, videoβ¦).
Exclusion of Generated Files
The team follows βWhat not to commitβ documentation to not include most of the files that the IDE, code editor, pub tool, and other tools generate. This also includes these various generated file extensions:
*.g.dart
*.gen.dart
*.config.dart
*.freezed.dart
*.mocks.dart
etc...
Excluding them benefits the team to:
- LinearB with substantial code changes from gen code.Avoid wrong statistics from
-
-
Hence, a code generator is necessary for local development or CI:
$ flutter packages pub run build_runner build --delete-conflicting-outputs
Development Environment
Code Editor
There is no specific editor is enforced at the team level. Flutter developers can pick what they are comfortable with but also what does not hinder their productivity.
The following options are the most widely used:
In addition, this will be needed:
- Xcode for iOS code inspection and editing.
Version Managers
Due to the diversity of projects the team works on, each application usually requires different versions of Flutter. Versions managers allow developers to install and switch between different versions effortlessly.
The following version manager(s) is recommended:
- fvm is the preferred version manager for Flutter.
Formatting
Methods
- Use soft-tabs with a two-space indent. For more indentation and spacing rules, follow the
-
-
Separate each abstract method using a blank line for better readability.
abstract class Human { void speak(); void run(); }
-
-
- Use the line break before each parameter in a method when it exceeds the line length.
-
Always use a line break for the method with more than two parameters.
void createAccount(String firstName, String lastName, String email, String phoneNumber) { // Your code }
void createAccount( String firstName, String lastName, String email, String phoneNumber, ) { // Your code }
-
Commas: Prefer to add a trailing comma
,
when there are more than 2 parameters in a method for auto-formatting in VSCode or Android Studio. This applies to Widget also.void setReminder({String? label, DateTime? datetime, bool? enableSnooze}) { // Your code }
void setReminder({ String? label, DateTime? datetime, bool? enableSnooze, }) { // Your code }
-
-
required
: should be at the same line as the parameters.void disableButton({ required Widget button, required Color color, })
void disableButton({ required Widget button, required Color color, })
-
Comments
- Comment should follow the
Widgets
-
Add
const
before the widget whenever possible. By adding this keyword, the constant widget is NOT re-rendered when rebuilding the parent widget, improving the application performance. Read further in this article The Flutter const keyword demystified.Center( child: const Text('Hello World!'), );
-
Prefer to split the code into small widgets to avoid
large nested trees
. The debugging process will become easy for checking the UI issue. Besides, the widget tree is readable and clean. This could be flexible when creating a widget class or a function that returns a widget.Scaffold( body: Column( children: [ // The Header Container( child: Stack( children: [ Column( children: [ Row( children: [ Column( children: [ Container( // A child ), ], ), ], ), Container( // A child ), ], ), ], ), ), // The Body Expanded( child: Row( children: [ Column( children: [ Row( children: [ ListTile( leading: Column( children: [ Container( // A child ), ], ), ), ], ), Container( // A child ), ], ), ], ), ), // The Footer Expanded( child: Column( children: [ Row( children: [ Container( // A child ), Container( // A child ), ], ), ], ), ), ], ), );
Scaffold( body: Column( children: [ _buildHeaderWidget(), BodyWidget(), FooterWidget(), ], ), ); Widget _buildHeaderWidget() { return Container( // The Header ); } class BodyWidget extends StatelessWidget { ... } class FooterWidget extends StatelessWidget { ... }
Naming
The standardized naming conventions from Effective Dart style are used and respected by the team, with a minor exception as outlined in the following guideline.
-
Capitalize acronyms and abbreviations no matter the length of letters.
class HTTPRequest {} class DBIOPort {} class TVVcr {}
class HttpRequest {} class DbIoPort {} class TvVcr {}
Localization
- l10n as a main localization.The team uses
-
.arb
files should follow the pattern{feature}{optionalWidgetName}{stringType}
and usecamelCase
format. For example:-
loginTitle
:login
is afeature
, andtitle
is astringType
. Thereβs only one title forlogin
, so thereβs no need to specifywidgetName
. -
loginPhoneNumberTitle
: This string looks similar to the above string, but this string is for thePhoneNumber
field. To differentiate from other titles,PhoneNumber
is specified as awidgetName
. -
errorInvalidPassword
: In this case,error
is a special type offeature
, andInvalidPassword
is astringType
.
-
-
feature
types can be named according to the application features list.
Package Id
-
-
application id
is used for an Android application, iOS applications call itbundle identifier
.- A valid
application id
allows alphanumeric characters, periods (.
), and underscores (_
). Read more about Application Id. - A valid
bundle identifier
allows alphanumeric characters, periods (.
), and hyphens (-
). Read more about CFBundleIdentifier.
- A valid