0% found this document useful (0 votes)
7 views

Week 3 - Asynchronous Programming and Iterables

flutter

Uploaded by

amnaahmad2072003
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Week 3 - Asynchronous Programming and Iterables

flutter

Uploaded by

amnaahmad2072003
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 34

EC303 – MOBILE APPLICATION DEVELOPMENT

FOR SMES
WEEK 3
OBJECTIVES

 Asynchronous Programming
 Iterable collection
ASYNCHRONOUS PROGRAMMING
WHY ASYNCHRONOUS CODE MATTERS

 Asynchronous operations let your program complete work while waiting for another
operation to finish. There are some common asynchronous operations which are :
• Fetching data over a network.
• Writing to a database.
• Reading data from a file.
WHY ASYNCHRONOUS CODE MATTERS

 Such asynchronous computations usually provide their result


 as a Future
 or, if the result has multiple parts, as a Stream.

 These computations introduce asynchrony into a program.


 To accommodate that initial asynchrony, other plain Dart functions also need to become
asynchronous.
 To interact with these asynchronous results, you can use the async and await keywords.
KEY TERMS

• Synchronous operation: A synchronous operation blocks other operations from


executing until it completes.
• Synchronous function: A synchronous function only performs synchronous operations.
• Asynchronous operation: Once initiated, an asynchronous operation allows other
operations to execute before it completes.
• Asynchronous function: An asynchronous function performs at least one asynchronous
operation and can also perform synchronous operations.
WHAT IS A FUTURE?

 A future (lower case "f") is an instance of the Future (capitalized "F") class.
 A future represents the result of an asynchronous operation and can have two states:
 Uncompleted
 Uncompleted is a Dart term referring to the state of a future before it has produced a value.

 Completed
 If the asynchronous operation succeeds, the future completes with a value. Otherwise, it completes with an
error.
COMPLETED

Completing with a value


 A future of type Future<T> completes with a value of type T.
 For example, a future with type Future<String> produces a string value.
 If a future doesn't produce a usable value, then the future's type is Future<void>.

Completing with an error


 If the asynchronous operation performed by the function fails for any reason, the future
completes with an error.
EXAMPLE – SYNCHRONOUS PROGRAMMING

String getName() => "Thunderbird";


void main(List<String> args) {
print(getName());
}

Output
Thunderbird
FUTURE

 Functions can return a Future


 Means results will be available in the future
 http.get(url)  HTTP GET request
 returns a Future that resolves to an http.Response object

 Some RESTFul API are synchronous, i.e they block


 Future move from Uncompleted Completed
 Can take time
WORKING WITH FUTURE

 The async and await keywords provide a declarative way to define asynchronous
functions and use their results.
 Remember these two basic guidelines when using async and await:
 To define an async function, add async before the function body:
 The await keyword works only in async functions.

 Here's an example that converts main() from a synchronous to asynchronous function.


 First, add the async keyword before the function body:

void main() async { ··· }


WORKING WITH FUTURE

 If the function has a declared return type, then update the type to be Future<T>, where T
is the type of the value that the function returns. If the function doesn't explicitly return a
value, then the return type is Future<void>:

Future<void> main() async { ··· }


 Now that you have an async function, you can use the await keyword to wait for a future to
complete:

print(await createOrderMessage());
EXAMPLE

Future<String> getName() async => "Thunderbird";


void main(List<String> args) {
print(getName().runtimeType);
}
EXAMPLE

Future<String> getName() async {


sleep(Duration(seconds: 3));
return "Thunderbird";
}

void main(List<String> args) {


print(getName());
}
EXAMPLE

Future<String> getName() async {


sleep(Duration(seconds: 3));
return "Thunderbird";
}

void main(List<String> args) async {


print(await getName());
}
EXAMPLE

Future<void> doSomethingAsync() async {


print('Starting...');
await Future.delayed(Duration(seconds: 1));
print('END of function!');
}

void main() {
print('Before calling doSomethingAsync');
doSomethingAsync();
print('Main');
}
THEN KEYWORD

 Basic Syntax

futureObject.then((result) {
// do something with the result of the future
}).catchError((error) {
// handle any errors that occur while processing the future
});
EXAMPLE

Future<int> addNumbers(int a, int b) {


return Future.delayed(Duration(seconds: 1), () => a + b);
}

void main() {
addNumbers(2, 3).then((result) {
print('The result is: $result');
}).catchError((error) {
print('An error occurred: $error');
});
}
EXAMPLE

Future<int> addNumbers(int a, int b) {


return Future.delayed(Duration(seconds: 1), () => a + b);
}

void main() {
addNumbers(2, 3).then((result) {
print('The result is: $result');
}).catchError((error) {
print('An error occurred: $error');
});
print("Hello");
}
TASK – PREDICT THE OUTPUT OF BOTH
String createOrderMessage() { Example: asynchronous functions #
var order = fetchUserOrder(); Future<String> createOrderMessage() async {

return 'Your order is: $order'; var order = await fetchUserOrder();

} return 'Your order is: $order';


}

Future<String> fetchUserOrder() =>


Future<String> fetchUserOrder() =>
// Imagine that this function is more
complex and slower. // Imagine that this function is more complex and
slower.
Future.delayed(
Future.delayed(
const Duration(seconds: 2),
const Duration(seconds: 2),
() => 'Large Latte',
() => 'Large Latte',
); );

void main() { Future<void> main() async {


print('Fetching user order...'); print('Fetching user order...');
print(createOrderMessage()); print(await createOrderMessage());
} }
ITERABLES COLLECTIONS IN DART
OVERVIEW

• Understand the power of Iterable collections in Dart.


• Learn how to efficiently work with Lists and Sets.
• Explore various methods and operations available for manipulation.
WHAT ARE COLLECTIONS?

 A collection is an object that represents a group of objects, which are called elements.
 Iterables are a kind of collection.
 A collection can be empty, or it can contain many elements.
 Depending on the purpose, collections can have different structures and implementations.
 These are some of the most common collection types:
 List: Used to read elements by their indexes.
 Set: Used to contain elements that can occur only once.
 Map: Used to read elements using a key.
WHAT IS AN ITERABLE?

 An Iterable is a collection of elements that can be accessed sequentially.


 In Dart, an Iterable is an abstract class, meaning that you can't instantiate it directly.
However, you can create a new Iterable by creating a new List or Set.
 Both List and Set are Iterable, so they have the same methods and properties as the
Iterable class.
 A Map uses a different data structure internally, depending on its implementation.
 For example, HashMap uses a hash table in which the elements (also called values) are obtained
using a key.
 Elements of a Map can also be read as Iterable objects by using the map's entries or values
property.
EXAMPLE

 This example shows a List of int, which is also an Iterable of int:

Iterable<int> iterable = [1, 2, 3];


 The difference with a List is that with the Iterable, you can't guarantee that reading
elements by index will be efficient. Iterable, as opposed to List, doesn't have the []
operator.
 For example, consider the following code, which is invalid:

Iterable<int> iterable = [1, 2, 3];


int value = iterable[1];
.ELEMENTAT()

 If you read elements with [], the compiler tells you that the operator '[]' isn't defined for
the class Iterable, which means that you can't use [index] in this case.
 You can instead read elements with elementAt(), which steps through the elements of the
iterable until it reaches that position.
Iterable<int> iterable = [1, 2, 3];
int value = iterable.elementAt(1);
READING ELEMENTS

 Sequentially access elements using for-in loop.

void main() {
const iterable = ['Salad', 'Popcorn', 'Toast'];
for (final element in iterable) {
print(element);
}
}
ACCESSING ELEMENTS

void main() {
 In some cases, you want to access only Iterable<String> iterable = const
the first or the last element of an ['Salad', 'Popcorn', 'Toast'];
print('The first element is $
Iterable.
{iterable.first}');
 With the Iterable class, you can't access print('The last element is $
the elements directly, so you can't call {iterable.last}');
iterable[0] to access the first element. }
Instead, you can use first, which gets the
first element.
 Also, with the Iterable class, you can't
use the operator [] to access the last
element, but you can use the last
property.
FINDING ELEMENTS

 Use firstWhere to find the first element that satisfies a condition.


CHECKING CONDITIONS

void main() {
const items = ['Salad', 'Popcorn', 'Toast'];
 The Iterable class provides
two methods that you can if (items.any((item) => item.contains('a'))) {
use to verify conditions: print('At least one item contains "a"');
 any(): Returns true if at least }
one element satisfies the
condition. if (items.every((item) => item.length >= 5)) {
 every(): Returns true if all print('All items have length >= 5');
elements satisfy the }
condition. }
FILTERING ELEMENTS

 Use where() to find elements meeting specific criteria.

var evenNumbers = numbers.where((number) => number.isEven);


for (final number in evenNumbers) {
print('$number is even');
}
MAPPING ELEMENTS

 Mapping Iterables with the method map() enables you to apply a function over each of the
elements, replacing each element with a new one.
Iterable<int> output = numbers.map((number) => number * 10);
 In this example, each element of the Iterable numbers is multiplied by 10.
 You can also use map() to transform an element into a different object—for example, to
convert all int to String, as you can see in the following example:
Iterable<String> output = numbers.map((number) => number.toString());
ANY QUESTIONS?

You might also like