Reader small image

You're reading from  Flutter Cookbook, Second Edition - Second Edition

Product typeBook
Published inMay 2023
Reading LevelIntermediate
PublisherPackt
ISBN-139781803245430
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
Simone Alessandria
Simone Alessandria
author image
Simone Alessandria

Simone Alessandria wrote his first program when he was 12. It was a text-based fantasy game for the Commodore 64. Now, he is a trainer (MCT), author, speaker, passionate software architect, and always a proud coder. He is the founder and owner of Softwarehouseit. His mission is to help developers achieve more through training and mentoring. He has authored several books on Flutter, including Flutter Projects, published by Packt, and web courses on Pluralsight and Udemy.
Read more about Simone Alessandria

Right arrow

Strings and string interpolation

A String is simply a variable that holds human-readable text. The reason why they're called strings instead of text has more to do with history than practicality. From a computer's perspective, a String is actually a list of integers. Each integer represents a character.

For example, the number U+0041 (Unicode notation, 65 in decimal notation) is the letter A. These numbers are stringed together to create text.

In this recipe, we will continue with the console application in order to define and work with strings.

Getting ready

  1. To follow along with this recipe, you should write this code in DartPad (https://dartpad.dev/). Remove any content inside the main() method.

How to do it...

Just like in the previous recipe, you are going to create a “hub” function. Inside it, every sub-function will show a different way of using strings:

  1. Type in the following code and use it as the hub for all the other string examples:
void stringPlayground...

How to write functions

Functions are the basic building blocks of any programming language and Dart is no different. The basic structure of a function is as follows:

optionalReturnType functionName(optionalType parameter1, optionalType parameter2...) {
  // code
} 

You have already written a few functions in previous recipes. In fact, you really can't write a proper Dart application without them.

Dart also has some variations of this classical syntax and provides full support for optional parameters, optionally named parameters, default parameter values, annotations, closures, generators, and asynchronicity decorators. This may seem like a lot to cover in one recipe, but with Dart, most of this complexity will disappear.

Let's explore how to write functions and closures in this recipe.

Getting ready

  1. To follow along with this recipe, you can write the code in DartPad. Begin with a clean Pad, with an empty main method.

How to do it...

We'll continue with the same pattern...

How to use functions as variables with closures

Closures, also known as first-class functions, are an interesting language feature that emerged from lambda calculus in the 1930s. The basic idea is that a function is also a value that can be passed around to other functions as a parameter. These types of functions are called closures, but there is really no difference between a function and a closure.

Closures can be saved to variables and used as parameters for other functions. They are even written inline when consuming a function that expects a closure as a property.

Getting ready

  1. To follow along with this recipe, you can write the code in DartPad.

How to do it...

To implement a closure in Dart, follow these steps:

  1. To add a closure to a function, you have to essentially define another function signature inside a function:
void callbackExample(void Function(String value) callback) {
  callback('Hello Callback');
}
  1. Under the callbackExample method, create another plain...

Creating classes and using the class constructor shorthand

Classes in Dart are not dramatically different from what you would find in other object-oriented programming (OOP) languages. The main differences have more to do with what is missing rather than what has been added. Dart can fully support most OOP paradigms, but it can also do so without a large number of keywords. Here are a few examples of some common keywords that are generally associated with OOP that are not available in Dart:

  • private
  • protected
  • public
  • struct
  • interface
  • protocol

It may take a while to let go of using these, especially for longtime adherents of OOP, but you don't need any of these keywords and you can still write type-safe encapsulated, object-oriented code.

In this recipe, we're going to define a class hierarchy around formal and informal names.

Getting ready

As with the other recipes in this chapter, add your code in DartPad. You may start with an empty main method.

How to do it...

Let&apos...

How to group and manipulate data with collections

All programming languages possess need ways to organize data. We've already covered the most common way – objects. These class-based structures allow you to define how you want to model your data and manipulate it with methods.

If you want to model groups of similar data, collections are your solution. A collection contains a group of elements. There are many types of collections in Dart, but we are going to focus on the three most popular ones: List, Map, and Set.

  • Lists are linear collections where the order of the elements is maintained.
  • Maps are a non-linear collection of values that can be accessed by a unique key.
  • Sets are a non-linear collection of unique values where the order is not maintained.

These three main types of collections can be found in almost every programming language, but sometimes by a different name. If Dart is not your first programming language, then this matrix should help you correlate collections...

Writing less code with higher-order functions

One of the main tasks every programmer should master is dealing with data. Our apps receive data from a source, be it a web service or some local database, and then we transform that data into user interfaces where we can collect more information and then send it back to the source. There is even an acronym for this – Create, Read, Update, and Delete (CRUD).

Throughout your life as a programmer, you will spend a lot of your time writing CRUD code. It doesn't matter if you are working with 3D graphics or training machine learning models – CRUD will consume a good part of your life as a developer.

Data manipulation and standard control flows are a good starting point. We can also add higher-order functions, one of the primary tools of functional programming, to help us manipulate data faster. Basically higher order functions are functions that take a function as an argument, or return a function.

Getting ready

Create a new...

How to take advantage of the cascade operator

So far, you’ve seen how Dart follows many of the same patterns of other modern languages. Dart, in some ways, takes the best ideas from multiple languages – you have the expressiveness of JavaScript and the type safety of Java.

However, there are some features that are unique to Dart. One of those features is the cascade (..) operator.

Getting ready

Before we dive into the code, let's diverge briefly to the builder pattern. Builders are a type of class whose only purpose is to build other classes. They are often used for complex objects with many properties. It can get to a point where standard constructors become impractical and unwieldy because they are too large. This is the problem the builder pattern solves. It is a special kind of class whose only job is to configure and create other classes.

This is how we would accomplish the builder pattern without the cascade operator:

class UrlBuilder {
  String _scheme;
  String...

Introducing Dart Null Safety

When Dart 2.12 was shipped in Flutter 2 in March 2021, an important language feature was added that impacts how you should view null values for your variables, parameters and fields: this is the sound null safety.

Generally speaking, variables that have no value are null, and this may lead to errors in your code. If you have been programming for any length of time, you are probably already familiar with null exceptions in your code. The goal of null safety is to help you prevent execution errors raised by the improper use of null.

With null safety, by default, your variables cannot be assigned a null value.

There are obviously cases when you want to use null, but you have to explicitly allow null values in your apps. In this recipe, you will see how to use null safety to your advantage, and how to avoid null safety errors in your code.

Getting ready

Create a new pad in Dartpad.

How to do it...

Let's see an example of null unsafe code, and then fix...

Using Null Safety in classes

While you’ve seen the basics of Null Safety in the previous recipe, you should also be aware of a few rules that should drive the way you design classes in Dart.

Getting ready

Create a new pad in Dartpad and remove the default code in the main method.

How to do it...

Let's see an example of a plain Dart class, with two properties. Follow these steps:

  1. Add a new class, with two strings and no value:
class Person {
  String name;
  String surname;
}

Note the compile error telling that the two fields are non-nullable

In the Person class, create a constructor that gives a value to the fields:

Person(this.name, this.surname);  

Note that the error is now fixed.

Add a named constructor, that takes a map of String, dynamic and creates an instance of Person:

Person.fromMap(Map<String, dynamic> map) {
    name = map['name'];
    surname = map['surname'];
}

Note the compile errors that shows in the console, requiring an...

Writing less code with higher-order functions

One of the main tasks every programmer should master is dealing with data. Our apps receive data from a source, be it a web service or some local database, and then we transform that data into user interfaces where we can collect more information and then send it back to the source. There is even an acronym for this—Create, Read, Update, and Delete (CRUD).

Throughout your life as a programmer, you will spend a lot of your time writing data manipulation code. It doesn’t matter if you are working with 3D graphics or training machine learning models—dealing with data will consume a good part of your life as a developer.

In Dart, higher-order functions are functions that take one or more functions as their arguments, or return a function. These provide a powerful tool to manipulate data because they allow you to write reusable and modular code that can be easily adapted to different scenarios. Higher-order functions...

How to take advantage of the cascade operator

So far, you’ve seen how Dart follows many of the same patterns of other modern languages. Dart, in some ways, takes the best ideas from multiple languages—you have the expressiveness of JavaScript and the type safety of Java.

However, there are some features that are unique to Dart. One of those features is the cascade (..) operator.

Getting ready

Before we dive into the code, let’s diverge briefly to the builder pattern. You can use this pattern to build complex objects with many properties. It can get to a point where standard constructors become impractical and unwieldy because they are too large. This is the problem the builder pattern solves. It is a special kind of class whose only job is to configure and create other classes.

This is how we would accomplish the builder pattern without the cascade operator:

class UrlBuilder {
  String? _scheme;
  String? _host;
  String? _path;
  UrlBuilder...

Using extensions

Extensions allow you to add methods and properties to existing classes, without modifying the original class.

With extensions, you extend the functionality of classes, and this is especially useful when you extend classes that you cannot modify.

Getting ready

To follow along with this recipe, you can write the code in DartPad.

How to do it...

To create a new method that extends the String class, follow these steps:

  1. Create an extension called StringExtensions for the String class that adds a method called toBool, which returns false when the string is empty, and true when it’s not:
    extension StringExtensions on String {
      bool toBool() {
        return isNotEmpty;
      }
    }
    
  2. Create a method that calls the toBool() method on two strings, one empty and another with some content:
    void testExtension() {
      String emptyString = "";
      String nonEmptyString = "Hello Extensions!";
      print(emptyString...

Introducing Dart Null Safety

When Dart version 2.12 was shipped in Flutter in March 2021, an important language feature was added that impacts how you should view null values for your variables, parameters, and fields: this is sound null safety.

Generally speaking, variables that have no value are null, and this may lead to errors in your code. If you have been programming for any length of time, you are probably already familiar with null exceptions in your code. The goal of null safety is to help you prevent execution errors raised by the improper use of null.

With null safety, by default, your variables cannot be assigned a null value.

There are obviously cases when you want to use null, but you have to explicitly allow null values in your apps. In this recipe, you will see how to use null safety to your advantage, and how to avoid null safety errors in your code.

Getting ready

Create a new Pad in DartPad.

How to do it...

Let’s see an example...

Using Null Safety in classes

While you’ve seen the basics of null safety in the previous recipe, you should also be aware of a few rules that should drive the way you design classes in Dart.

Getting ready

Create a new pad in DartPad and remove the default code in the main method.

How to do it...

Let’s see an example of a plain Dart class, with two properties. Follow these steps:

  1. Add a new class, with two Strings and no value:
    class Person {
      String name;
      String surname;
    }
    
  2. Note the compile error saying that the two fields are non-nullable.
  3. In the Person class, create a constructor that gives a value to the fields:
      Person(this.name, this.surname);  
    
  4. Note that the error is now fixed.
  5. Add a named constructor that takes a map of String, dynamic and creates an instance of Person:
    Person.fromMap(Map<String, dynamic> map) {
        name = map['name'];
        surname = map...

Summary

In this chapter, you have seen an introduction to some of the core concepts of Dart programming, starting with the basics of variable declaration, where you have seen how to use var, final, and const, and their differences.

You have seen how to use strings and string interpolation, which allow you to add expressions within a string, making it easier to create dynamic strings. Dart supports string interpolation using the $ symbol for variables and ${} to evaluate an expression within a string.

You have seen different ways to use functions, and their positional, optional, and named parameters. You have also treated functions as values in first-class functions, and seen how to use higher-order functions, which allow you to write less code by passing functions as arguments to other functions.

You have seen how to work with collections, including List, Set, and Map.

You have used the cascade operator, which allows you to chain multiple method calls on an object...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Flutter Cookbook, Second Edition - Second Edition
Published in: May 2023Publisher: PacktISBN-13: 9781803245430
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Simone Alessandria

Simone Alessandria wrote his first program when he was 12. It was a text-based fantasy game for the Commodore 64. Now, he is a trainer (MCT), author, speaker, passionate software architect, and always a proud coder. He is the founder and owner of Softwarehouseit. His mission is to help developers achieve more through training and mentoring. He has authored several books on Flutter, including Flutter Projects, published by Packt, and web courses on Pluralsight and Udemy.
Read more about Simone Alessandria