0% found this document useful (0 votes)
22 views13 pages

Event Loop in Dart

The document provides an overview of key concepts in Dart and Flutter, including the event loop, async/await functionality, and layout principles in Flutter. It explains how constraints flow from parent to child widgets, how sizes are determined, and how parents position their children. Additionally, it covers Riverpod state management, detailing various provider types and their usage for managing state in Flutter applications.

Uploaded by

vickyrocker
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views13 pages

Event Loop in Dart

The document provides an overview of key concepts in Dart and Flutter, including the event loop, async/await functionality, and layout principles in Flutter. It explains how constraints flow from parent to child widgets, how sizes are determined, and how parents position their children. Additionally, it covers Riverpod state management, detailing various provider types and their usage for managing state in Flutter applications.

Uploaded by

vickyrocker
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 13

Event Loop in Dart

 Dart is a single-threaded language.


 Dart uses an event loop to schedule asynchronous tasks.
 Dart always executes synchronous code immediately. It only
executes the tasks in the microtask queue once the synchronous
tasks are empty. And it only executes the tasks in the event queue
once both synchronous tasks and the microtask queue are empty.

https://www.dhiwise.com/post/how-dart-
event-loop-influence-the-execution-dart-code

Async Await in Dart


When an await expression is encountered, the
function is suspended, and control is returned to
the caller until the awaited operation completes.
Once the awaited operation finishes, the function
resumes execution from where it left off.
Container
When you create a Container and give it a child widget, remember that
it's the parent widget in the render tree that decides the Container's size.

SizedBox

If given a child, this widget forces it to have a specific width and/or


height. These values will be ignored if this widget's parent does not permit
them.

Difference between Container and SizedBox


The main differences lie in the way a container creates a more decorated
box for its child widget to sit in. On the other hand, SizedBox acts like a box
widget that has a constant height and width for its child widget.

Understanding constraints
Constraints go down. Sizes go up. Parent sets position.

In Flutter, understanding the layout system is crucial for building


responsive and visually appealing user interfaces. The rule "Constraints
go down. Sizes go up. Parent sets position." is a guideline to help
developers comprehend how Flutter's layout mechanism works. Let's
break it down:

Constraints go down
This means that the parent widget imposes constraints on its children.
Constraints define the minimum and maximum width and height that a
child widget can have. These constraints are passed from the parent to
the child during the layout phase.

For example, consider a Container widget inside a Column. The Column


will provide constraints to the Container, such as how wide it can be and
how tall it can be. These constraints are determined based on the
parent's size and the specific properties of the layout widgets involved.

Column(
children: [
Container(
width: 100, // Explicit width constraint
height: 50, // Explicit height constraint
color: Colors.red,
),
],
)
In this case, the Container receives constraints from the Column, and it
will use these constraints to decide its own size.

Sizes go up
After a child widget receives constraints from its parent, it decides its
own size based on these constraints. Once the child widget has
determined its size, it reports this size back to the parent.

Continuing with the previous example, the Container decides that it will
be 100 pixels wide and 50 pixels tall (as specified). This size information
is then reported back to the Column.

Parent sets position


Finally, the parent widget uses the sizes reported by its children to
determine their positions within itself. The parent widget places its
children based on their sizes and any layout properties (like padding,
alignment, etc.).

For instance, the Column will position the Container within its own layout
according to the specified alignment. By default, children in a Column
are positioned one after another vertically.

Putting it all together


Consider the following complete example:

class MyWidget extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Container(
width: 100, // Child decides its width
height: 50, // Child decides its height
color: Colors.red,
),
Container(
width: 150, // Child decides its width
height: 70, // Child decides its height
color: Colors.blue,
),
],
),
),
);
}
}
Constraints go down: The Column widget imposes constraints on its
children. Each Container receives these constraints, which might limit
their maximum width and height.
Sizes go up: Each Container decides its size (100x50 for the red one,
150x70 for the blue one) within the given constraints and reports these
sizes back to the Column.
Parent sets position: The Column uses the sizes of its children to
position them. In this case, it stacks them vertically one after another
based on their reported sizes.
By following these principles, Flutter ensures a flexible and efficient
layout process where parents control constraints and positions, while
children determine their own sizes within those constraints.
Understanding constraints
Constraints go down. Sizes go up. Parent sets position.
import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {


const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Flutter Layout Rule')),
body: Center(
child: Container(
color: Colors.blue,
width: 200,
height: 200,
child: Container(
width: 100,
height: 100,
color: Colors.red,
child: const Text('Hello, World!'),
),
),
),
),
);
}
}
Explanation of the Layout Process
Constraints go down:
The Center widget centers its child within itself and passes down loose constraints allowing the child to
be as small or as large as it wants (within the constraints of the screen size).
The outer Container (blue) receives these loose constraints from the Center. It then passes constraints down to
its child (the inner Container).
Sizes go up:
The outer Container (blue) specifies its own size as 200x200, within the constraints it received from the
Center.
The inner Container (red) receives the constraints from its parent (the blue Container). Since it has
specified its own width and height as 100x100, it chooses this size within the constraints provided by the blue
Container.
Parent sets position:
The Center positions the blue Container at the center of the available space.
The blue Container then positions the red Container at the top-left corner of its own bounding box, because the
default alignment for a Container's child is the top-left corner.

Visual Representation
Here's a step-by-step visualization:
Step 1: The Center widget centers its child (the blue Container) in the middle of the screen.
Step 2: The blue Container sets its own size to 200x200 pixels.
Step 3: The blue Container passes constraints to its child (the red Container), allowing it to be at most 200x200
pixels.
Step 4: The red Container sets its own size to 100x100 pixels.
Step 5: The blue Container positions the red Container at the top-left corner of the 200x200 space it occupies.
Step 6: The text "Hello, World!" is placed inside the red Container.
Conclusion
This example demonstrates the layout rule in Flutter effectively:

Constraints go down: Constraints flow from the Center to the blue Container, and then to the red
Container.
Sizes go up: The red Container determines its size (100x100), which is then used by the blue Container
(200x200) to finalize its own layout.
Parent sets position: The Center positions the blue Container in the center, and the blue Container
positions the red Container at its top-left corner.

Factory Constructors
Factory constructors are a key part of Flutter. They can return an
instance of a class that is either a fresh instance or an instance that has
been previously created, i.e., an existing instance. This is different from
a default constructor which always returns a new instance. The factory
constructor can also return an instance of a different class.

Encoding and Decoding


Encoding and serialization are the same thing—turning a data
structure into a string. Decoding and deserialization are the opposite
process—turning a string into a data structure.
However, serialization also commonly refers to the entire process of
translating data structures to and from a more easily readable format.

Wireless Debugging Steps

1. Go to C:\Android\sdk\platform-tools> or where adb.exe exists in your


computer

2. Run ".\adb pair" command


3. Then Run ".\adb pair 192.168.0.193:37889 429215" -> .\adb pair
PHONEIP:PORT_NUMBER PAIR_CODE from the mobile

4. Then Run ".\adb connect PHONEIP:PORT_NUMBER PAIR_CODE from the


mobile

Riverpod State Management

Riverpod

Riverpod is a Reactive State Management and Dependency Injection


Framework that is the enhanced version of Provider.

Types of Riverpod Providers

 Provider
o It is used to store immutable objects
 StateProvider
o It is used to store simple mutable objects like string,
enum,number, boolean etc…
 StateNotifierProvider
 NotifierProvider
 FutureProvider
 StreamProvider
 ChangeNotifierProvider

ProviderScope

It will stores all the state of the providers which we will create in our
application.

Behind the scene it actually creates the instance of Provider


Container.

Riverpod Provider

It is an object that encapsulates a piece of state and allows listening


to that state.

Provider Syntax & Use

final nameProvider = Provider<String>((ref) { return 'Hello


World; });

nameProvider -> Is a global variable that is used to read the state of


the provider

Provider<String> -> What typeof provider we are using and <Type


of state> it holds

It is used for accessing dependencies and objects that are


immutable

May be used to access Repository, Service and some other class


that are immutable

Read Provider Data

The Riverpod Provider that we created is outside the widget tree.

To read the value from the Provider we need ref object which is of
type WidgetRef

There are many ways to read data from provider

1. By extends the stateless widget by ConsumerWidget


2. If the widget is Stateless widget by using Consumer
3. By extends the stateful widget by ConsumerStatefulWidget
and extends the State by using ConsumerState

Difference between ref.watch and ref.read

ref.watch -> is used inside the build method. Whenever the


provider value changed it automatically rebuilds the widget

ref.read -> is used to read the provider value once

Update provider object value

To update the provider value one of the following 2 methods can be


used

1. Use ref.read(providerName.notifier).state++;
2. Use ref.read(providerName.notifier).update((state) => state+1;);

To reset the StateProvider state value

1. Use invalidate
2. Use refresh

To listen to the provider value changes

To listen to the provider value changes use ref.listen

ref.listen(counterProvider, ((previous, next) {

if (next == 5) {

Scaffold Messenger. of (context)showSnackBar (SnackBar


(content: Text('The value is $next'))

}));

StateNotifierProvider

StateNotifierProvider is a provider that is used to listen to and


expose a State Notifier

StateNotifierProvider along with StateNotifier is Riverpod's


recommended solution for managing state which may change in reaction
to a user interaction.
Used for centralizing the Business Logic in a single place, improving
maintainability over time.

Notifier

To update the state of a provider from within Consumer we need to


use Notifier

Notifiers are the "stateful widget" of providers.

Syntax is as follows:

final name =
SomeNotifierProvider.someModifier<MyNotifier,Result>(MyNotifier.new);

class MyNotifier extends SomeNotifier<Result> {

@override

Result build() {

<your logic here>

<your methods here>

Aspect NotifierProvider AsyncNotifierProvider


Asynchronous (AsyncValue<T>, handling
State Type Synchronous (plain data)
loading, data, error)
Notifier
Extends Notifier<T> Extends AsyncNotifier<T>
Class
Use Case Simple state management, no Asynchronous operations like API calls or
Aspect NotifierProvider AsyncNotifierProvider
async logic database queries
Example Future<String>, Stream<List<T>>,
int, bool, String, List
State AsyncValue<T>
State Synchronous (immediate
Asynchronous (delayed/fetched state)
Changes updates)
Error Built-in error handling with
Manual error handling
Handling AsyncValue.error

You might also like