Flutter For Beginners#3- Dart Crash Course

Flutter For Beginners#3- Dart Crash Course

When Google started working on Flutter, they had an early decision to make: what programming language would it use? It could be a web-based language like JavaScript, or perhaps the natural choice would have been Java given that Android uses that. Or, since support for iOS was something that they of course desired, maybe Swift would be a good choice, maybe something like Golang or Ruby would be better. I’m certain there were a lot of option available, but in the end, Google decided to go with a language that they themselves had created a few years earlier: Dart. This entire article is devoted to Dart.

A little Background

Google created Dart back in 2011, and it was initially unveiled at the GOTO conference in Aarhus, Denmark. The initial 1.0 (stable release) took place in November 2013, roughly two years before Flutter was released. Dart is a neat language that is getting a lot of attention.

But What’s Dart all about?

  • Dart is fully object-oriented.
  • It has a C, Java, JavaScript -based syntax style, (you can say it picked the best syntax from these languages) this makes it easy for most developers to pick up faster
  • A sound typing system
  • Dart can use JIT(just in time compilation) and can use ahead-of-time compilation to native code in order to reach the highest levels of performance, It compiles to ARM and x86 code, it can also trans pile to JavaScript so your Dart code can run, even on the web!. In this series, we mostly will end up with AOT-compiled Dart code.
  • Dart supports a large package repository that provides additional functionality on top of the core language and makes it easy to bring those packages to use in your projects.
  • Tooling support from a lot of popular developer tools including Visual Studio Code(which we will be using in this series) and Android Studio.

We have gotten a brief introduction to Dart, the language Google chose for Flutter, given that all flutter apps are built with Dart it’s something you must have a good grasp of, and this, is what this article is all about. You will get to understand Dart programming language.

Before we proceed, let me introduce you to DARTPAD, an online code editor, specially made for DART. It allows you to run dart codes quickly and easily without having to install anything on your system(which is pretty cool, s you can write a code on it and share to someone else). Head over to dartpad.dartlang.org and check it out. This is a Dart crash course which simply means am only going to briefly touch the Basic concepts we need to get started developing mobile apps with flutter, we will learn other advance Dart concepts as we dive deeper into Flutter

Alright let’s get back to our learning.

LET’S MAKE SOME COMMENTS

Comments are part of your code that your compiler ignores during your code execution.

There are 3 types of comments in Dart

  1. One Single line comment
//This is a question class; the compiler ignores everything on this line
Question {

}
  1. Multi-Line Comments
/*
This variable stores a value
For other functions to use, the compiler ignores everything between these markers
*/
final klonty = 34;
  1. Documentation comments. These comments are designed to produce useful verbiage when documentation generation tooling is used on Dart code. These can be either single-line or multi-line by using the /// or /* and / sequences:
/// This is a documentation comment.
/**This, too, is a documentation comment. */

LET’S KEEP YOUR VALUES: VARIABLES

To begin with, everything is an object in Dart, even simple numbers, functions, and even null are all objects, they all extend from a common Object class. In Dart You can declare a variable many ways:

var b = “Bazeleel Nwabia”;
String b =” Bezaleel Nwabia”;

And in ‘var b’ something interesting happens, Dart will intelligently infer the type from the value assigned. In this case, it knows that the value “Bezaleel Nwabia” is a type of String. You can also declare the type explicitly, as in String b, any works. And there are other types

dynamic b = “Bezaleel Nwabia”;

Here, the dynamic type annotation tells Dart that what b references can change over time. So, if later you do

b = 21;

Dart won’t complain that b now points to an integer rather than a string. And yes, there are also

int b = 2; //this tells Dart the value is an integer
double b = 2.0; //this tells Dart the value is an integer
bool b = true; //this tells Dart the value is a Boolean

And also, yes you can create your own type!

As at the time of writing this article, Dart is in version 3.x and by default doesn’t like null variables, Compiler will yell at you, and your code won’t even run, except you explicitly run your code informing your compiler that you have nulled variables which was later assigned a value somewhere in your code

LET ME INTRODUCE YOU TO THE TWO UNIDENTICAL SIBLINGS (CONSTANTS AND FINAL)

The const and final keywords, define a variable as being a constant and a final immutable value respectively:

const b = "Bezaleel Nwabia";

Surprise! Surprise!! It works with type annotations too! :

const String b = "Bezaleel Nwabia";

And you can use final instead if you prefer:

final b = "Bezaleel Nwabia";

And yes, even though they behave like twins, there is a difference. const variables are constant at compile-time, which means their value can’t depend on anything at runtime. So, if you tried:

const d = DateTime.now(); //this won’t work. 
final x = DateTime.now(); //But, this will

Essentially, final means you can only set it once, but you can do so at runtime, while const means you can only set it once, but its value must be knowable at compile-time.

Everyone Has a Type: STRING TYPE:

Dart offers a String Data Type; they can be initialized using single or double quotation marks.

String b9 = “Legend of Bazz”;
String b6 = “Legend of Bezaleel”;
Print(b9); //this prints the value b9 to the screen
Print(b6);

And yes, you can add/concatenate two or more strings, see various concatenation examples below:

print(‘Bezaleel’, “Nwabia”); //will display Bezaleel Nwabia to the screen
return “Bezaleel”, “Nwabia”;

you can also concatenate variable’s

String b3 = “Bazz”;
String b12 = ‘Li’;
Print(‘${b3} ${b12} is truly a flutter genius’); // will display Bazz Li is truly a flutter genius to the screen

NUMERIC TYPE:

Dart has two types of numeric values. integer values identified with int, double values identified with double. Both int and double are subclasses of num, so if you aren’t sure whether a variable value will remain an integer, you can define the variable as num num b15 = 2; or num b18 = 2.0; as well as int b15 = 2; or double b18 = 2.0; are all valid.

BOOLEAN TYPE:

Boolean values are of type bool, and only two objects have Boolean values: the keywords true and false (which are compile-time constants).

LISTS AND MAPS:

The List class in Dart is same as array in JavaScript.

List z1 = [1, 2, 3, 4, 5, 6];

and

z1 = [1, 2, 3, 4, 5, 6];

are both the same thing.

A list uses a zero-based indexing scheme, so list.length-1 gives you the index of the last element. You can access elements by index:

print (z1[1]); // this will display 2

A list, being an object, has several methods available on it. Here’s a quick example of a few of them:

List z10 = [ 9, 8, 7];
z10.add (6);
z10.removeLast();
print (z10.indexOf(3));
print(z10);

Dart also offers a Set class, which is similar to List, but it’s an unordered list, which means you can’t retrieve elements by index, you have to use methods contains() and containsAll() instead:

Set cookies = Set();
cookies.addAll([ “milk”, "oatmeal", "chocolate", "biscuit" ]);
cookies.add("cornflakes"); 
cookies.remove("biscuit");
print(cookies);
print(cookies.contains("oatmeal")); //this will print a Boolean value which is true
print(cookies.containsAll([ "chocolate", "rainbow" ])); //this will print a Boolean value which is false

Dart also has a Map class, sometimes called a dictionary an instance of which can be created in many ways:

var meats = Map();
meats["Goat"] = "red meat";
meats["chicken"] = "white meat";
print (meats);

var movies = Map<String, int>();
movies["Hulk"] = 4;
movies["Thor"] = 3;
print(movies);

var actors = {
"Ryan Reynolds" : "Deadpool",
"Hugh Jackman" : "Wolverine"
};
print(actors);

What’s Your Type: The “as” and “is” Keywords

These two go together: the is keyword allows you to determine if a value is of a given type while as allows you to treat a given type reference as another, assuming it’s a superclass. For example:

if (shape is Circle) {
print(circle.circumference);
}

This will only print the circumference if shape is of type Circle. By contrast, you can use as like so:

(shape as Circle).circumference = 20;

That way, if shape is a Circle, it works as expected, and if shape can be cast to a Circle, then it would work too (perhaps shape is of type Oval, which is a subclass of Circle, for example). Note, however, that in the example of is, nothing will happen if shape isn’t a Circle, but in the as example, an exception will be thrown if shape can’t be cast to Circle.

FLOW CONTROL STATEMENTS AND CONSTRUCTS

LOOPING:

Looping in Dart takes on the familiar for, do, and while loop forms:

//for statement
for (var i = 0; i < 10; i++) {
print(i);
}

//while statement
while (!isDone()) {
// Do something
}

//dowhile statement
do {
showStatus();
}while (!processDone());

The continue keyword is also available in Dart to skip to the next iteration of a loop construct. There is also a break keyword to exit from a loop early.

And everyone’s favorite logic statement

IF STATEMENTS

In Dart if statements condition expressions must always evaluate to a Boolean value

If (2 is int){
    Print(‘2 is an integer’);
    } else{
Print(‘2 is not an integer’)
}

DART OPERATORS

Dart has a robust set of operators for you to work with. Refer to the dart docs(dart.dev/guides/language/language-tour#oper..) for list of Dart operators

LET'S CLASS UP:

OBJECT ORIENTATION IN DART:

Dart is object-oriented, which means we’re dealing with classes and objects. Defining a class is as simple as

class Hero { }

INSTANCE VARIABLES:

Instance variables are variables declared inside a class. Any instance variable that you don’t initialize with a value begins with a value of null, and dart by default doesn’t like it and yes there is a way around it,

late String somevariable; //by marking it late the compiler partially ignores it

But it’s a very good practice to declare a variable when you are absolutely sure some values will be assigned

Dart also automatically generates a getter method for each variable , which simply means you can access the variable outside the class

Person() {
    String firstName = ‘Bezaleel’;
    }
p1 = Person();
print (p1.fistName); // this will print Bezaleel

Instance variables can be marked as static as well, which means you can use them without instantiating the class, like I did above:

class MyClass {
static String greeting = "Hi";
}
main() {
print(MyClass.greeting);
} //This will print “Hi”, all without ever creating an instance of MyClass

METHODS:

Methods are simply functions inside a class, so whenever you hear methods just know it’s a member function of a class

Class DevPerson{
    bool mobileDev = true;
    bool webDev = false;
    String nameOfDev = ‘Temi’
    String sayTypeOfDev () {
Return “is ${nameOfDev} a Mobile App Developer : ${mobileDev} . ”
}
}

We’re going to look at functions in more detail soon. Now we have sayTypeOfDev() method that we could call like so:

Main(){
DevPerson dvp1 = DevPerson();
dvp1.mobileDev = false;
dvp1.webDev = true;
dvp1.nameOfDev = ‘Johnson’;
print(dvp1.sayTypeOfDev());
}

Dart also automatically creates a setter method for us, which is why dvp1.nameOfDev = “Johnson”; works. Methods can also be marked as static, just like instance variables can be, and pretty much works same way

CONSTRUCTORS

Constructors is a special function inside a class that executes when an instance of that class is created

class Hero {
String firstName = ‘Bezaleel’;
String lastName = Nwabia;
Hero(this.firstName, this.lastName);
String sayName() {
return "$lastName, $firstName";
}
}

subclasses do not inherit constructors.

Subclassing

We discussed about subclasses here a moment ago, so how do we define those? Well, it’s easy:

class Hero {
  String firstName = "Bezaleel";
  String lastName = "Nwabia";
  Hero.build(this.firstName, this.lastName); //named constructor
  String sayName() {
    return "$lastName, $firstName";
  }
}

class UltimateHero implements Hero {
  UltimateHero(fn, ln) : super.build(fn, ln);
  @override
  String sayName() {
    return "Jedi $lastName, $firstName";
  }
}

void main() {
  UltimateHero dev1 = UltimateHero('Bezalel', 'Nwabia') ;//this is an instance of the class Ultimate Hero
  print( dev1.sayName());//prints Jedi Bezaleel Nwabia to the Screen
}

The implements keyword, followed by the name of the class we want to subclass, is all it takes.

AM I VISIBLE

In Java and many other OOP languages, you typically need to specify what access code has to class members using keywords like public, private, and protected. Dart is different: everything is public unless it begins with an underscore, which marks it as being private to its library, or class. So whenever you see an a variable, function that starts with underscore, then it’s a private to the class its part of (you can’t access it from outside the class) or Dart file (which simply put, you can’t access it from another Dart file)

Phewww, that was a lot! But it covers Basics of what I think you’ll need to know about classes and objects in Dart.

FUNCTIONS

In Dart, functions are first-class citizens and have their own type: Function. What that means is that functions can be assigned to variables, can be passed as parameters, and can also be stand-alone entities. There’s one key stand-alone function you’re already aware of, and that’s main(). Functions in dart can have named parameters and they can also have optional parameters, And parameters can be positional or named parameters (you can only use one style at a time, you can’t mix both)

greet(String name) {
  print("Hello, $name");
}

class MyClass {
  greetAgain({dynamic f, String n = "human"}) {
    f(n);
  }
}

main() {
  MyClass greetPerson = new MyClass();
  greet("Chukwuemeka");
  greetPerson.greetAgain(f: greet, n: "Kehinde");//this is a great example of named parameters
  greetPerson.greetAgain(f: greet);
}

Here you can see most of what you will do with function at work. First we have a stand alone greet() function. Then, we have a class with a greetAgain() method. This method accepts a named parameter list, and look, one of those parameters is dynamic (we passed a function to it, in the main function). Also, see how the n parameter has a default value of human defined. Inside the function, we call the function referenced by f, passing another value to n, overriding the default value ‘human’.

In many languages, the data you pass to functions are called arguments. that’s the term i grew up with learning Python and JavaScript, but the Dart language seem to prefer parameters. truthfully, i may mix those terms sometimes, but they mean the same thing.

Most functions you might have encountered have a name, but they can also be anonymous (without name). Take a look at this example

void main() {
    var sayMyName = (name){print(“your name is ${name}”);};
    }

As you can see, I created a function without a name and assigned to the variable sayMyName. Dart also supports arrow, or lambda, notation for defining functions. So, these are same thing:

yu() { print("123"); }
yu() => print("123");//this is a syntactic sugar and is more useful if an expression inside a function can be in one line

ARE YOU GOING TO AWAIT ME? ASYNCHRONOUS PROGRAMMING

Its everywhere in all languages and Dart is no exception. In Dart, two classes are key to asynchrony, Future and Stream, along with two keywords, async and await. Both classes are objects that async functions return when a long-running operation begins, but before it completes, allowing the program to await the result while continuing to do other things, then continue where it left off when the result comes back. To call a function that returns a Future, you use the await keyword:

await aLongRunningFunction();

That’s all you have to do! Your code will pause at this line until aLongRunningFunction() completes. The program can still do other things rather than being blocked by the long-running operation. There’s one more key piece of information: the function that calls aLongRunningFunction() must itself be marked as async:

myFunction() async {
await aLongRunningFunction();
}

Streams are handled in much the same way, but to read data from the Stream you must use an async for loop:

await for (varOrType identifier in expression) {
// Executes each time the stream emits a value.
}

The difference between the two is simply that using a Future means that the return from the long-running function won’t occur until that function completes, however long it takes. With a Stream, the function can return data little by little over time, and your code that is awaiting it will execute any time the Stream emits a value. You can break or return from the loop to stop reading form the Stream, and the loop will end when the async function closes the Stream.

SUMMARY

Pheww that's alot you just learnt. But you got a pretty good understanding on Dart, you learned about the basics like data types, operators, comments, logic, and flow control. You also learned some, mid-level stuff, things like classes and Object orientation. Finally, you got an introduction into some slightly more advanced topics such as asynchronous programming. You should now have the basic understanding of dart, enough to get started, developing beautiful apps with Flutter. We will discuss and learn the advanced parts of Dart as we explore Flutter. In the next article we dive straight into Flutter!