Chapter 7: Advanced Dart
Learning Flutter
Learning Resource: Free Flutter Course by Vandad Nahavandipoor on YouTube.
Introduction
In this chapter we are going to look into advanced Dart concepts such as; Extension, Streams, Async/Await, Generators.
Extensions
Extensions are the ability for a programmer to extend or add functionality to an existing class.
Now let’s see how an extension is used in a code:
class Cat {
final String name;
Cat(this.name);
}
extension Run on Cat {
void run() {
print("Cat $name is running");
}
}
void test() {
final meow = Cat("Fluffers");
meow.run();
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result:
Cat Fluffers is running
Let’s take a look at how we could use extension to get a Full Name:
class Person {
final String firstName;
final String lastName;
Person(this.firstName, this.lastName);
}
extension FullName on Person {
String get fullName => "$firstName $lastName";
}
void test() {
final foo = Person("Foo", "Bar");
print(foo.fullName);
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result:
Foo Bar
Future
Future is a data to be returned in the future, as its name suggests.
Let’s look into Future;
Future<int> heavyFutureThatMultipliesByTwo(int a) {
return Future.delayed(const Duration(seconds: 3), () {
return a * 2;
});
}
void test() {}
// Call Site
@override
Widget build(BuildContext context) {
test();
}But in other to use Future, we have to learn about async/await.
Async/Await
Async and Await are similarly related to each other but quite different in there meaning.
Async is a keyword in Dart that marks a function as asynchronous. Remember Synchronous is something that returns immediately while Asynchronous is something that doesnt return immediately, it takes some time.
So both Async & Await are the mechanism for controlling asynchronous flow of data.
But first of all, let’s look into this code without Async & Await:
Future<int> heavyFutureThatMultipliesByTwo(int a) {
return Future.delayed(const Duration(seconds: 3), () {
return a * 2;
});
}
void test() {
final result = heavyFutureThatMultipliesByTwo(10);
print(result);
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result: Instance of ‘_Future<int>’
Note:
As we can see, the code recognizes our
result = heavyFutureThatMultipliesByTwo(10)
as an Instance of ‘_Future<int>’
Now let’s look into the code with Async & Await present inside of it:
Future<int> heavyFutureThatMultipliesByTwo(int a) {
return Future.delayed(const Duration(seconds: 3), () {
return a * 2;
});
}
void test() async {
final result = await heavyFutureThatMultipliesByTwo(10);
print(result);
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result: 20
Note:
Once Async & Await came into play in our code, the code understood that although it will delay for 3 seconds, but it has to multiply whatsoever the parameter we set our (int a) to by 2.
Since int a is set to 10.
Then 10 * 2 would be multiplied but the result will be delayed by 3 seconds.
Streams
An asynchronous “pipe” of data that either completes successully or never completes or it bails out and dies.
Get GlobalDami’s stories in your inbox
Join Medium for free to get updates from this writer.
Let’s check out how we can use streams in our code:
Stream<String> getName() {
return Stream.value("Foo");
}
void test() async {
await for (final value in getName()) {
print(value);
}
print("Stream finished working");
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result:
Foo
Stream finished working
Above is a very simple stream code and can done with Future similarly.
Now let’s look into a more complex code that shows the true capacity of Streams:
Stream<String> getName() {
return Stream.periodic(const Duration(seconds: 1), (value) {
return "Foo";
});
}
void test() async {
await for (final value in getName()) {
print(value);
}
print("Stream finished working");
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result:
Foo
(Based on the periodic parameter we have in place as 1 second. It keeps printing Foo every second. Since it is endless stream, it never gets to print our second line of code which says “Stream finished working”).
Generators
Generators are very interesting in Dart and some other languages also support Generators but not all modern programming languages do that.
A Generator in Dart is a function that returns a list of things but it internally calculates that data in a very simple way.
Let’s look into a code with function that creates a generator:
Iterable<int> getOneTwoThree() sync* {
yield 1;
yield 2;
yield 3;
}
void test() {
for (final value in getOneTwoThree()) {
print(value);
if (value == 2) {
break;
}
}
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result:
1
2
Note:
The above is a synchronous Generator function.
Now, let’s check out what an asynchronous Generator function looks like:
Stream<Iterable<int>> getOneTwoThree() async* {
yield [1];
yield [2];
yield [3];
}
void test() async {
await for (final value in getOneTwoThree()) {
print(value);
}
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result:
[1]
[2]
[3]
Note:
I just carried out an asynchronous Generator function but my instructor stated that it is rarely used. But it is good to know that it actually exists.
Generics
Generics in programming languages like Dart that do support it, are there to avoid writing the same code over and over again.
Let’s check out the code below to see how Generic is used in a program:
class PairOfStrings {
final String value1;
final String value2;
PairOfStrings(this.value1, this.value2);
}
class PairOfIntegers {
final int value1;
final int value2;
PairOfIntegers(this.value1, this.value2);
}
class Pair<A, B> {
final A value1;
final B value2;
Pair(this.value1, this.value2);
}
void test() {
final names = Pair("foo", "bar");
print(names.value1);
}
// Call Site
@override
Widget build(BuildContext context) {
test();
}Result: foo
What’s coming in the next chapter?
We need to set up our project structure in the next chapter.
I am happy to know that the next chapter would be focused on putting all the basics I have learned into practice and start building.
#Dart #AdvancedDart #Extensions #Future #Async #Await #Streams #Generator #Generics #Flutter #Google #LogicalDami










