Do's and Don'ts for performance best practices in flutter/dart

The objective of this article is to give you a quick summary of do and don’ts in other words prefer and avoid based on coding standards from tech giants.

You might or might not agree with some of the best practices presented here, and that’s absolutely fine as long as there is some coding standard in place.

Why do we need coding standards?

A coding standard ensures that all developers writing the code in a particular language write according to the guidelines specified. This makes the code easy to understand and provides consistency in the code.

Let’s explore some of the best practices in designing and developing Flutter app.

Use only relative imports for files in lib/

While developing  application we create multiple files with in our lib folder and import it in one another. Use of absolute and relative together can create confusion, To avoid this we should use relative imports for files.

Specify types for class members/variables

Always specify the type of member when it's value type is know. avoid using var when possible. as var is dynamic type take more space and time to resolve.

Naming convention

Naming conventions make sure programmer know how to name variable and classes so  that they will be consistent and contain all the right information.

Classes, enums, typedefs, and extensions name should in UpperCamelCase.

Packages ,Libraries, Directories, and source files name should be in snake_case(lowercase_with_underscores).

Variables, constants, parameters, and named parameters should be in lowerCamelCase.

Use of Null safe (??) and Null aware (?.) operators

Prefer using ?? (if null) and ?. (null aware) operators instead of null checks in conditional expressions. It reduces code and make code more cleaner.

Use spread collections

We often append one collection with other , spread collection syntax leads to simpler code.

Avoid using as instead, use is operator

Use of as operator can throw an exception if the cast is not possible. To avoid this exception, we can use is.

Don’t explicitly initialize variables null

Adding redundant and unneeded code is bad practices for any language out there, In Dart, the variable is automatically initialized to null when its value is not specified, so is adding null is redundant and unneeded.

Avoid print() calls

You use debugPrint when you want more information about what is being printed to the console. The additional information is usually useful for debugging. Also  Android sometimes discards some log lines. To avoid this, use debugPrint().

Use ListView.builder for a long list

Unless an app is very basic and created for learning purposes, it will always use dynamic data i.e. Contents of the screen will change based on user actions and/or with change in network data.

Most of the time, the dynamic behaviour is achieved by changing the contents that is being displayed in the body. Flutter provides ListView.builder which can be used to generate dynamic contents from external sources.

Default ListView constructor builds the whole list at once. ListView.builder creates a lazy list and when the user is scrolling down the list, Flutter builds widgets on-demand.

Use of state management appropriately

Choosing suitable state management for particular functionality is very important using setState for every state change is not good practices

Flutter offers following state managements

  • Provider
  • setState
  • InheritedWidget & InheritedModel
  • Redux
  • Fish-Redux
  • BLoC / Rx
  • MobX
  • GetX

You can learn more at https://flutter.dev/docs/development/data-and-backend/state-mgmt

Split Widget into different Widgets

When setState() is called on state, all descendent widget will rebuild Therefore split widgets into small widgets so the setState() call can affect only subtrees whose UI actually needs to be change

Thank you for reading, I hope this gives you a few tips to make your Flutter code more readable while also improving your app’s performance. Keep coding!