learn you some rx for the greater good

Post on 16-Jul-2015

151 Views

Category:

Technology

6 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Artur Glier

RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM

✓ Microsoft Reactive Extensions by Erik Meijer

Fast forward

✓ Microsoft Reactive Extensions by Erik Meijer✓ Netflix RxJava & RxJs by Ben Christensen

Fast forward

✓ Microsoft Reactive Extensions by Erik Meijer✓ Netflix RxJava & RxJs by Ben Christensen✓ Github ReactiveCocoa

Fast forward

✓ Microsoft Reactive Extensions by Erik Meijer✓ Netflix RxJava & RxJs by Ben Christensen✓ Github ReactiveCocoa (Think different...)

Fast forward

Some of early adopters

RxJava is all about FRP

✓ Programming with asynchronous data streams

FRP is...

✓ Programming with asynchronous data streams

+✓ Toolbox

FRP is...

✓ Cross platform ;)✓ A fun new tool. “If you only have a hammer -

you tend to see each problem as nail.”✓ Less error prone✓ ! a steep learning curve

FRP is...

@interface RACSignal (Operations)

- (RACSignal *)doNext:(void (^)(id x))block;

- (RACSignal *)doError:(void (^)(NSError *error))block;

- (RACSignal *)doCompleted:(void (^)(void))block;

- (RACSignal *)throttle:(NSTimeInterval)interval;

- (RACSignal *)throttle:(NSTimeInterval)interval valuesPassingTest:(BOOL (^)(id next))predicate;

- (RACSignal *)delay:(NSTimeInterval)interval;

- (RACSignal *)repeat;

- (RACSignal *)initially:(void (^)(void))block;

- (RACSignal *)finally:(void (^)(void))block;

- (RACSignal *)bufferWithTime:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler;

- (RACSignal *)collect;

- (RACSignal *)takeLast:(NSUInteger)count;

- (RACSignal *)combineLatestWith:(RACSignal *)signal;

+ (RACSignal *)combineLatest:(id<NSFastEnumeration>)signals;

+ (RACSignal *)combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock;

- (RACSignal *)merge:(RACSignal *)signal;

+ (RACSignal *)merge:(id<NSFastEnumeration>)signals;

- (RACSignal *)flatten:(NSUInteger)maxConcurrent;

...

@end

RxJava is an extension of the observer desing pattern

� It’s pull-based approach and any logic requires the result to be available at execution time

Iterables

� Futures are straight-forward to use for a single level of asynchronous execution

� Conditional asynchronous execution flows become difficult to optimally compose

Futures

� They are easy to use with a single level of asynchronous execution but become unwieldy with nested composition.

Callbacks

� Producer can signal consumer that there is no more data available

� Producer can signal consumer that error has ocurred

Observer Pattern

How do you learn RxJava?

BY example

RxJava is all about FRP

FRP is...✓ Responsive, Reslient,

Elastic, Message Driven “FRP manifesto”

✓ Rx = Observables + LINQ + Schedulers “Microsoft”

✓ Programming paradigm for reactive programming using the building blocks of functional programming “Wikipedia”

✓ … “stackoverflow”

FRP is...✓ Responsive, Reslient,

Elastic, Message Driven “FRP manifesto”

✓ Rx = Observables + LINQ + Schedulers “Microsoft”

✓ Programming paradigm for reactive programming using the building blocks of functional programming “Wikipedia”

✓ … “stackoverflow”

FRP is...✓ Responsive, Reslient,

Elastic, Message Driven “FRP manifesto”

✓ Rx = Observables + LINQ + Schedulers “Microsoft”

✓ Programming paradigm for reactive programming using the building blocks of functional programming “Wikipedia”

✓ … “stackoverflow”

FRP is...✓ Responsive, Reslient,

Elastic, Message Driven “FRP manifesto”

✓ Rx = Observables + LINQ + Schedulers “Microsoft”

✓ Programming paradigm for reactive programming using the building blocks of functional programming “Wikipedia”

✓ … “stackoverflow”

FRP is...✓ Responsive, Reslient,

Elastic, Message Driven “FRP manifesto”

✓ Rx = Observables + LINQ + Schedulers “Microsoft”

✓ Programming paradigm for reactive programming using the building blocks of functional programming “Wikipedia”

✓ … “stackoverflow”

Bla, bla, bla...

Rx.Observable.prototype.flatMapLatest(selector, [thisArg])Projects each element of an observable sequence into a new

sequence of observable sequences by incorporating the element's

index and then transforms an observable sequence of observable

sequences into an observable sequence producing values only from

the most recent observable sequence.

BY example

RxJava is all about marbles

Not this kind of marbles

This kind of marbles

RxJava is all about code

Observable<String> observable = Observable.just("Hello, World!");

Subscriber<String> subscriber = new Subscriber<String>() {

@Override

public void onCompleted() {

// code here

}

@Override

public void onError(Throwable e) {

// code here

}

@Override

public void onNext(String s) {

output.append(String.format("%s\n", s));

}

};

@Override

protected void onStart() {

super.onStart();

observable

.observeOn(Schedulers.newThread())

.subscribeOn(AndroidSchedulers.mainThread())

.subscribe(subscriber);

}

Request compositionpublic interface AftonbladetAPI {

@GET("/item/{id}.json")

Observable<Item> item(@Path("id") long id);

@GET("/topstories.json")

Observable<List<Long>> topStories();

}

Request compositionGET /topstories

[ 8414149, 8414078, 8413972, 8411638, 8414102, 8413204, 8413100, 8413971,

8412744, 8414003, 8412841, 8412802, 8412605, 8413548, 8413123, 8414437,

8412897, 8413028, 8413341, 8412425, 8411762, 8413623, 8412346, 8411356,

8413056, 8413365, 8412372, 8414055, 8412877, 8412167, 8413264, 8414137,

8410519, 8412933, 8411846, 8412929, 8411254, 8411512, 8412777, 8412626,

8413274, 8414389, 8414117, 8412114, 8412212, 8412759, 8412696, 8412768,

8411643, 8411866, 8413966, 8410976, 8410545, 8410358, 8413979, 8414129,

8411791, 8409075, 8410314, 8411532, 8411553, 8412099, 8412085, 8410356,

8409084, 8412862, 8409823, 8412705, 8410220, 8409323, 8414090, 8410326 ]

Request compositionGET item/8863.json{

"by": "Daniel Söderbäck",

"id": 1,

"score": 111,

"time": 1415793648,

"title": "Swede Jacobson won the Poker World Championships",

"type": "story",

"url": "http://www.aftonbladet.se/sportbladet/poker/article19844615.ab"

}

Request compositionpublic void onRefresh() {

Aftonbladet.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> Aftonbladet.API.item(id))

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request composition - flatMap()public void onRefresh() {

Aftonbladet.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> Aftonbladet.API.item(id))

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request composition - flatMap()public void onRefresh() {

Aftonbladet.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> Aftonbladet.API.item(id))

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request composition - collect()public void onRefresh() {

Aftonbladet.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> Aftonbladet.API.item(id))

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request composition - threadspublic void onRefresh() {

Aftonbladet.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> Aftonbladet.API.item(id))

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request compositionpublic void onRefresh() {

Aftonbladet.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> Aftonbladet.API.item(id))

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request composition.subscribe(

items -> list.setAdapter(new ArrayAdapter<Item>(..., ..., items)),

error -> handleError(error),

() -> {

if (ptr.isRefreshing()) ptr.setRefreshing(false);

}

)

Request composition - filter()public void onRefresh() {

HackerNews.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> HackerNews.API.item(id))

.filter(item -> item.time > 1412985600)

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request composition - limit()public void onRefresh() {

HackerNews.API.topStories()

.flatMap(longs -> Observable.from(longs))

.flatMap(id -> HackerNews.API.item(id))

.filter(item -> item.time > 1412985600)

.limit(10)

.collect(new ArrayList<Item>(), (items, item) -> items.add(item))

.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(...);

}

Request compositionObservable.zip(

service.getUserPhoto(id),

service.getPhotoMetadata(id),

(photo, metadata) -> createPhotoWithData(photo, metadata))

.subscribe(photoWithData -> showPhoto(photoWithData));

public static Observable<String> getRegIdObservable(final Context context) {

return Observable.create(new Observable.OnSubscribe<String>() {

@Override

public void call(Subscriber<? super String> subscriber) {

try {

subscriber.onNext(getDeviceRegId(context));

subscriber.onCompleted();

} catch (Exception e) {

subscriber.onError(e);

}

}

});

}

GcmUtils.getRegIdObservable(this)

.subscribeOn(Schedulers.newThread())

.observeOn(Schedulers.newThread())

.subscribe(new Action1<Topic>() {

@Override

public void call(Topic topic) {

API.subscribeToTopic(/* ... */);

}

});

RxJava is all about fun

Questions?

artur.glier@schibsted.pl

Refactoring Android to RxJava

top related