Top 7 Dart tips and tricks for cleaner Flutter apps

Feb 08, 2021 - 6 min read
Amanda Fawcett
editor-page-cover

Dart is a client-optimized programming language for quickly building mobile, desktop, and server apps. Dart was developed by Google to be used with their cross-platform Flutter framework. With Flutter and Dart, you can build apps that with slick UI and a native feel.

Today, we offer our top 7 Dart tips that will help you improve your app development. You can use these tips to write concise code and make the most of the many features that Dart has to offer.

Tips and tricks at a glance:

  1. Use anonymous functions as arguments
  2. Use the call method to make classes callable like a function
  3. Use .entries to iterate through a map
  4. How to use Getters and Setters
  5. Use a Set for a collection of unique items
  6. Make use of the Inspect Widget
  7. Use Sync and Async Generators
  8. Next steps for your learning

Take a deep dive into Dart 2 features

Learn the new Dart 2 language features. You’ll become confident with extensions, enums, mixins, generics, and more.

Developing Web Applications with Dart


1. Use anonymous functions as arguments

In the Dart language, functions can be passed as arguments to other functions. Dart provides anonymous functions that do not need a name and can be used directly.

Below is an example of an anonymous function in Dart. Here, we pass an anonymous cube function to a built-in method forEach. We are trying to get the cube for every item in a list.

main() {
  var list = [1,2,3];
  list.forEach((item) {
   print(item*item*item);
  });
}

We can also pass anonymous functions as a arguments to other functions. This approach to your code is useful when you use functional operators (like map, reduce, or where).

Below is an example where we define an anonymous function and assign it to a variable.

void main() {
  final sayHello = (name) => 'Hey, $name';
  intro(sayHello, 'Amanda');
}

void intro(String Function(String) greet,
             String name) {
  print(greet(name));
  print('Build cool Flutter apps');
}

sayHello is passed to the intro function, which takes the Function argument. On line 6, String Function(String) is a function type that returns a string from a given string argument. The anonymous function we use has the same signature, so it is passed as an argument.


2. Use the call method to make classes callable like a function

With Dart, you can create a callable class that allows that class instance to be called as a function. We do this with the call() method. See the syntax below.

class class_name {
  ... // class 
  
  return_type call ( parameters ) {
    ... // call the function content
  }
  
}

Let’s see this in action with an example.

class EducativeIntro { 
    
  // Defining call method 
  String call(String a, String b, String c) => 'Welcome to $a$b$c'; 
} 
  
// Main Function 
void main() { 
  var educative_input = EducativeIntro(); 
    
  // Calling the class through its instance 
  var educative_output = educative_input('our ', 'Dart ', 'tutorial'); 
    
  print(educative_output); 
}

Note: Dart doesn’t support multiple callable methods.


3. Use .entries to iterate through a map

In Dart, you can iterate through a map in a null-safe manner? using entries. Say we have a map that tracks the amount of money spent on different products. Typically, we’d iterate through this map with the ! operator.

for (var key in moneySpent.keys) {
  final value = moneySpent[key]!;
  print('$key: $value');
}

We can improve this code and make it more null-safe using a loop. When we iterate with the entires variable, we can access our key-value pairs in a null-safe manner.

for (var entry in moneySpent.entries) {
  // do something with keys and values
  print('${entry.key}: ${entry.value}');
}

Get up to date with Dart

Learn Dart and its updates without scrubbing through videos or documentation. Educative’s text-based courses are easy to skim and feature live coding environments, making learning quick and efficient.

Developing Web Applications with Dart


4. How to use Getters and Setters

Getters and setters are special methods that provide read and write access to an object’s properties. Getters and setters are called similar to instance variables: a dot operator (.) simply followed by the function name.

Getters are functions that are used to retrieve the values of an object’s properties. We use the get keyword.

Below is an example where we create a getter function on line 13 that will return the value of name of the current instance. On line 21, we call the getter function and the output should display Sarah.

class Person{
  String name; 
  String gender; 
  int age; 
  
  Person(this.name, this.gender, this.age);

  Person.newBorn(){
    this.age = 0;
  }

  // Getter function getting the value of name
  String get personName => name;

  walking() => print('$name is walking');
  talking() => print('$name is talking');
}

int main() {
  var firstPerson = Person("Sarah","Female",25);
  print(firstPerson.personName);
}

Setters are functions that are used to write the values of an object’s properties. We use the set keyword.

class Person{
  String name; 
  String gender; 
  int age; 

  String get personName => name;

  // Setter function for setting the value of age
  void set personAge(num val){
    if(val < 0){
      print("Age cannot be negative");
    } else {
      this.age = val;
    }
  } 

  walking() => print('$name is walking');
  talking() => print('$name is talking');
}

int main() {
  var firstPerson = Person();
  firstPerson.personAge = -5;
  print(firstPerson.age);
}

From line 9 to line 15, we create a setter function that sets the value for age. We also give it a condition so that we cannot input a negative age. And on line 23, we set the value of age for firstPerson using the personAge setter function.


5. Use a Set for a collection of unique items

A list is one of the most common collection types in Dart, but lists can hold duplicate items. Sometimes, we want only a collection of unique values. This is where a Set is useful.

final countriesSet = {
  'USA',
  'India',
  'Iceland',
  'USA', 
};

In a Set, two elements cannot be equal, so the code above will offer a warning and it won’t compile. This is also true if we use const set.


6. Make use of the Inspect Widget

In web development, it’s common to use the Inspect element, which will tell you all the properties applied to an HTML tag. Dart provides a similar feature called the Inspect Widget that can make app development with Flutter easier. The Flutter Widget Inspector can be used to locate any widget on the screen and view the properties applied to it.

The inspector can also help you visualize Flutter widget trees to understand layouts or identify layout issues

To use it, follow these steps:

  • Click on the Flutter inspector
  • Click on the Enable Select Widget Mode
  • Select a widget on the screen to get more information on it
Source: Flutter Documentation
Source: Flutter Documentation

7. Use Sync and Async Generators

In Dart, generators make it possible to produce a sequence of values. There are two generator functions:

  • Synchronous Generator: returns an iterable object
  • Asynchronous Generator: returns a Stream object

In other words, the synchronous generator returns a collection of values that can be accessed sequentially. We do this by marking the function body as sync*. Then, we use yield statements for the values.

Iterable<int> count(int n) sync* {
  for (var i = 1; i <= n; i++) {
    yield i;
  }
}

The asynchronous generator, on the other hand, returns a Stream object. A Stream makes it possible to receive a sequence of events. We do this by marking the function body as async*. Then, we use use yield statements for the values.

Stream<int> countStream(int n) async* {
  for (var i = 1; i <= n; i++) {
    yield i;
  }
}

Next steps for your learning

We hope these tips help you make the most of Dart and all the features it offers. Flutter and Dart are a powerful pair for building apps that feel native and slick. Other advanced Dart tools to investigate next are:

  • Spread operators for nested if-statements
  • Named constructors and initializer lists
  • Dart libraries
  • Enumerated types

To get hands-on practice with Dart and learn what new features it offers, check out Educative course Developing Web Applications with Dart. You will dive deep into Dart 2 language features and become confident with Dart extensions, enums, mixins, generics, libraries, and more.

Happy learning!


Continue learning about Dart and app development


WRITTEN BYAmanda Fawcett

Join a community of 500,000 monthly readers. A free, bi-monthly email with a roundup of Educative's top articles and coding tips.