This is the 19th day of my participation in the August More Text Challenge. In preparation for the Nuggets’ August challenge, I’m bringing you some dart-related tips from my development

1. You know what? Dart supports string multiplication.

This is a simple program that shows how to print a Christmas tree using string multiplication:

void main() { for (var i = 1; i <= 5; I ++) {print('🎄' * I); }} / / Output: / / 🎄 / / 🎄 🎄 / / 🎄 🎄 🎄 / / 🎄 🎄 🎄 🎄 / / 🎄 🎄 🎄 🎄 🎄Copy the code

Isn’t that cool? 😉

You can use it to check how long strings fit into the Text widget:

Text('You have pushed the button this many times:' * 5)
Copy the code

2. Need to execute multiple Futures at the same time? Use Future. Wait.

Consider this simulation API class, which tells us the latest number of COVID-19 cases:

// Mock API class
class CovidAPI {
  Future<int> getCases() => Future.value(1000);
  Future<int> getRecovered() => Future.value(100);
  Future<int> getDeaths() => Future.value(10);
}
Copy the code

To execute all of these futures at the same time, use future.wait. This requires a list or futures** and returns a future of lists:

final api = CovidAPI(); final values = await Future.wait([ api.getCases(), api.getRecovered(), api.getDeaths(), ]); print(values); / / [1000, 100, 10]Copy the code

This is ideal when the futures are independent, and they don’t need to execute sequentially.

3. Implement “call” methods in the Dart class to make them callable as functions.

Here is an example of the PasswordValidator class:

class PasswordValidator { bool call(String password) { return password.length > 10; }}Copy the code

Since the method is called Call, we can declare an instance of the class and use it as a method:

final validator = PasswordValidator();
// can use it like this:
validator('test');
validator('test1234');
// no need to use it like this:
validator.call('not-so-frozen-arctic');
Copy the code

4. Need to call the callback but only if it is not null? The use of “? Grammar. The call () “.

Suppose we have a custom widget class that should call the callback onDragCompleted when a specific event occurs:

class CustomDraggable extends StatelessWidget { const CustomDraggable({Key key, this.onDragCompleted}) : super(key: key); final VoidCallback? onDragCompleted; void _dragComplete() { // TODO: Implement me } @override Widget build(BuildContext context) {/*... * /}}Copy the code

To invoke the callback, we can write the following code:

  void _dragComplete() {
    if (onDragCompleted != null) {
      onDragCompleted();
    }
  }
Copy the code

But there is an easier way (careful use? .). :

Future<void> _dragComplete() async { onDragCompleted? .call(); }Copy the code

5. Use anonymous functions and functions as arguments

In Dart, functions are first-class citizens that can be passed as arguments to other functions.

Here is some code that defines anonymous functions and assigns them to the sayHi variable:

void main() {
  final sayHi = (name) => 'Hi, $name';
  welcome(sayHi, 'Andrea');
}
​
void welcome(String Function(String) greet,
             String name) {
  print(greet(name));
  print('Welcome to this course');
}
Copy the code

SayHi is then passed to a welcome Function that takes a Function argument and greets the user with it.

String Function(String) is a Function type that takes a String argument and returns a String. Because the anonymous function above has the same signature, it can be passed directly as a parameter or as a variable.


When using operators such as functions, this coding style is common to map, WHERE, and Reduce.

For example, here’s a simple function to square a number:

int square(int value) { // just a simple example // could be a complex function with a lot of code return value * value;  }Copy the code

Given a list of values, we can map them to get a square:

const values = [1, 2, 3];
​
values.map(square).toList();
Copy the code

Here we pass Square as a parameter because its signature is exactly what the map operator expects. This means we don’t need to extend it with anonymous functions:

values.map((value) => square(value)).toList();
Copy the code

6. You can use collect-if AND spreads with lists, sets AND maps

Collection-if and Spreads are very useful when you write the UI as code.

But did you know that you can also use them with Maps?

Consider this example:

const addRatings = true; const restaurant = { 'name' : 'Pizza Mario', 'cuisine': 'Italian', if (addRatings) ... {'avgRating': 4.3, 'numRatings': 5,}};Copy the code

Here we declare a Restaurantmaps and just add avgRating and numRatings key-value pairs if addRatings is true. Since we are adding multiple key-value pairs, we need to use the extension operator (…). .

7. Do YOU need to traverse the map in an air-safe way? use.entries:

Suppose you have a map:

Const timeSpent = <String, double>{'Blogging': 10.5, 'YouTube': 30.5, 'Courses': 75.2,};Copy the code

Here’s how to write a loop to run some code with all the key-value pairs:

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

By iterating through entries variables, you can have null-safe access to all key-value pairs.

This is much cleaner and less error-prone than this:

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

The code above! You need to use the assertion operator () when reading values because Dart does not guarantee the existence of a value for a given key.