Skip to content

Instantly share code, notes, and snippets.

@palexs
Last active April 18, 2019 12:36
Show Gist options
  • Save palexs/2b131df28a1315ba7c160735b9543bfc to your computer and use it in GitHub Desktop.
Save palexs/2b131df28a1315ba7c160735b9543bfc to your computer and use it in GitHub Desktop.
Streams are a way to get data from one place in our app to another.
*** DART FUNCTION PARAMS ***
void test1({ int one, String two: 'default' }) {
print(one);
print(two);
}
void test2(int main, { int one }) {
print(main);
print(one);
}
void main() {
test1(one: 1, two: 'two');
test1(one: 2);
test1();
test2(100, one: 111);
}
// OUTPUT:
1 two
2 default
null default
100 111
*** DART SIMPLE STREAM ***
import 'dart:async';
void main() {
// Initialize a "Single-Subscription" Stream controller.
final StreamController ctrl = StreamController();
// Initialize a single listener which simply prints the data as soon as it receives it.
final StreamSubscription subscription = ctrl.stream.listen((data) => print('$data'));
// Add the data that will flow inside the stream.
ctrl.sink.add('my name');
ctrl.sink.add(1234);
ctrl.sink.add({'a': 'element A', 'b': 'element B'});
ctrl.sink.add(123.45);
// Release the StreamController.
ctrl.close();
}
*** DART SIMPLE STREAM WITH TRANSFORMER ***
import 'dart:async';
void main() {
// Initialize a "Broadcast" Stream controller of integers.
final StreamController<int> ctrl = StreamController<int>.broadcast();
// Initialize a single listener which filters out the odd numbers and only prints the even numbers.
final StreamSubscription subscription = ctrl.stream
.where((value) => (value % 2 == 0))
.listen((value) => print('$value'));
// Add the data that will flow inside the stream.
for (int i = 1; i < 11; i++) {
ctrl.sink.add(i);
}
// Release the StreamController.
ctrl.close();
}
*** DART STREAMS ***
import 'dart:async';
class Cake {}
class Order {
String type;
Order(this.type);
}
void main() {
final order = new Order('chocolate');
// Order processor aka "Baker"
// Puts the result back to the stream via `sink.add/addError`
final baker = new StreamTransformer.fromHandlers(
handleData: (orderType, sink) { // 1st argument is the result of `map` function
if (orderType == 'chocolate') {
sink.add(new Cake());
} else {
sink.addError('I cannot bake that type!');
}
}
);
final controller = new StreamController();
controller.sink.add(order); // Order taking
controller.stream
.map((order) => order.type) // Order inspection/processing
.transform(baker) // Order processing
.listen( // Order output
(cake) => print('Here is your cake: $cake!'), // Value that successfully passed through the stream (`sink.add`)
onError: (err) => print('Error: $err') // Value that failed to pass through the stream (`sink.addError`)
);
}
*** TERMINOLOGY ***
Dart RxDart
---- ------
Stream Observable
StreamController Subject
RxDart extends the original Dart Streams API and offers 3 main variations of the StreamController:
PublishSubject
--------------
The PublishSubject is a normal broadcast StreamController with one exception: stream returns an Observable rather than a Stream.
PublishSubject sends to a listener only the events that are added to the Stream after the time of the subscription.
BehaviorSubject
---------------
The BehaviorSubject is also a broadcast StreamController which returns an Observable rather than a Stream.
The main difference with a PublishSubject is that the BehaviorSubject also sends the very last event that was emitted to the listener that just subscribed.
ReplaySubject
-------------
The ReplaySubject is also a broadcast StreamController which returns an Observable rather than a Stream.
A ReplaySubject, by default, sends all the events that were already emitted by the Stream to any new listener as the very first events.
*** STREAM BUILDER ***
// Flutter offers a very convenient StatefulWidget, called StreamBuilder.
// A StreamBuilder listens to a Stream and, each time some data goes out that Stream,
// it automatically rebuilds, invoking its builder callback.
StreamBuilder<T>(
key: ...optional, the unique ID of this Widget...
stream: ...the stream to listen to...
initialData: ...any initial data, in case the stream would initially be empty...
builder: (BuildContext context, AsyncSnapshot<T> snapshot){
if (snapshot.hasData){
return ...the Widget to be built based on snapshot.data
}
return ...the Widget to be built if no data is available
},
)
*** BLoC Design Guidelines ***
1. Inputs and outputs are simple Sinks/Streams only.
2. Dependencies must be injectable and platform agnostic.
3. No platform branching allowed.
4. Prefer reactive programming.
*** UI Design Guidelines ***
1. Each "complex enough" component has a corresponding BLoC.
2. Components should send inputs "as is".
3. Components should show outputs as close as possible to "as is".
4. All branching should be based on simple BLoC boolean outputs.
@palexs
Copy link
Author

palexs commented Apr 4, 2019

*** BLoC Diagram ***
Screen Shot 2019-04-04 at 11 23 55 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment