intro to retrofit 2 and rxjava2

46
Introduction to Retrofit 2 and RxJava 2 Fabio Collini Google I/O extended Florence May 2017

Upload: fabio-collini

Post on 21-Jan-2018

1.188 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: Intro to Retrofit 2 and RxJava2

Introduction to Retrofit 2 and RxJava 2

Fabio Collini

Google I/O extended Florence May 2017

Page 2: Intro to Retrofit 2 and RxJava2

2

Ego slide

@fabioCollini linkedin.com/in/fabiocollini github.com/fabioCollini medium.com/@fabioCollini codingjam.it Android programmazione avanzata

Page 3: Intro to Retrofit 2 and RxJava2

3

Retrofit

Turns your REST API into a Java interface Simple to use JSON conversion using Gson Custom converters  …

Page 4: Intro to Retrofit 2 and RxJava2

4

RxJava

A Java VM implementation of ReactiveX (Reactive Extensions): a library for composing asynchronous

and event-based programs by using observable sequences.

Page 5: Intro to Retrofit 2 and RxJava2

5

RxJava is not simple…

Page 7: Intro to Retrofit 2 and RxJava2

7

HTTP request definition

public interface StackOverflowService { @GET("/users") Call<List<User>> getTopUsers();

@GET("/users/{userId}/top-tags") Call<List<Tag>> getTags(@Path("userId") int userId); @GET("/users/{userId}/badges") Call<List<Badge>> getBadges(@Path("userId") int userId);}

Page 8: Intro to Retrofit 2 and RxJava2

8

Other annotations

@GET, @POST, @PUT, @DELETE, @HEAD @Path @Query @QueryMap @Body @FormUrlEncoded @Field @Headers

Page 9: Intro to Retrofit 2 and RxJava2

OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(chain -> { Request request = chain.request(); HttpUrl url = request.url().newBuilder() .addQueryParameter("site", "stackoverflow") .addQueryParameter("key", “...”) .build(); request = request.newBuilder().url(url).build(); return chain.proceed(request); }) .build();Gson gson = new GsonBuilder() .registerTypeAdapterFactory(MyAdapterFactory.create()) .create();

StackOverflowService service = new Retrofit.Builder() .baseUrl("http://api.stackexchange.com/2.2/") .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(okHttpClient) .addConverterFactory(new DenvelopingConverter(gson)) .addConverterFactory(GsonConverterFactory.create(gson)) .build() .create(StackOverflowService.class);

9

Service creation

Page 10: Intro to Retrofit 2 and RxJava2

10

Synchronous request

try { Response<List<User>> response = service.getTopUsers().execute(); if (response.isSuccessful()) { List<User> users = response.body(); //... } else { //server error } } catch (IOException e) { //connection error}

Page 11: Intro to Retrofit 2 and RxJava2

11

Asynchronous request

service.getTopUsers().enqueue(new Callback<List<User>>() { @Override public void onResponse(Call<List<User>> call, Response<List<User>> r) { if (r.isSuccessful()) { List<User> users = response.body(); //... } else { //server error } } @Override public void onFailure(Call<List<User>> call, Throwable t) { //connection error } });

Page 12: Intro to Retrofit 2 and RxJava2

12

Callback hell enqueue(service.getTopUsers(), new MyCallback<List<User>>() { @Override public void onResponse(List<User> users) { User user = users.get(0); enqueue(service.getTags(user.id()), new MyCallback<List<Tag>>() { @Override public void onResponse(List<Tag> tags) { enqueue(service.getBadges(user.id()), new MyCallback<List<Badge>>() { @Override public void onResponse(List<Badge> badges) { callback.onResponse(UserStats.create(user, tags, badges)); } @Override public void onFailure(Throwable throwable) { callback.onFailure(throwable); } }); } @Override public void onFailure(Throwable throwable) { callback.onFailure(throwable); } }); } @Override public void onFailure(Throwable throwable) { callback.onFailure(throwable); }});

Page 13: Intro to Retrofit 2 and RxJava2

+ RxJavaRetrofit

13

public interface StackOverflowService { @GET("/users") Call<List<User>> getTopUsers();}_

Page 14: Intro to Retrofit 2 and RxJava2

14

Retrofit + RxJava

public interface StackOverflowService { @GET("/users") Single<List<User>> getTopUsers();}_

Page 15: Intro to Retrofit 2 and RxJava2

15

RxJava in action

service.getTopUsers() .subscribe( users -> { if (users.size() > 5) users = users.subList(0, 5); System.out.println(users); }, Throwable::printStackTrace );

Page 16: Intro to Retrofit 2 and RxJava2

16

Threading

service.getTopUsers() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread) .subscribe( users -> { if (users.size() > 5) users = users.subList(0, 5); System.out.println(users); }, Throwable::printStackTrace );

Page 17: Intro to Retrofit 2 and RxJava2

17

Single

(onSuccess | onError)?

Page 18: Intro to Retrofit 2 and RxJava2

18

Observable

onNext* (onComplete | onError)?

Page 19: Intro to Retrofit 2 and RxJava2

19

Observable creation

Observable.just(1, 2, 3);

Observable.interval(5, TimeUnit.SECONDS);

Observable.fromCallable(() -> { //... return createFirstValue();});

Observable.create(emitter -> { try { emitter.onNext(createFirstValue()); emitter.onNext(createSecondValue()); emitter.onComplete(); } catch (Throwable t) { emitter.onError(t); }});

Page 20: Intro to Retrofit 2 and RxJava2

20

Observable in action

public Disposable subscribe( Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete);

Observable.just(1, 2, 3).subscribe( System.out::println, Throwable::printStackTrace, () -> System.out.println("Completed") );

Page 21: Intro to Retrofit 2 and RxJava2
Page 22: Intro to Retrofit 2 and RxJava2

22

service.getTopUsers() .subscribe( users -> { if (users.size() > 5) users = users.subList(0, 5); System.out.println(users); }, Throwable::printStackTrace );

Page 23: Intro to Retrofit 2 and RxJava2

23

service.getTopUsers() .map(users -> users.size() > 5 ? users.subList(0, 5) : users) .subscribe( System.out::println, Throwable::printStackTrace );

Page 24: Intro to Retrofit 2 and RxJava2
Page 25: Intro to Retrofit 2 and RxJava2

25

zip

private Single<UserStats> loadUserStats(User user) { return Single.zip( service.getBadges(user.id()),__ service.getTags(user.id()),___ (badges, tags) -> UserStats.create(user, tags, badges) );}_

Page 26: Intro to Retrofit 2 and RxJava2

26

zip

private Single<UserStats> loadUserStats(User user) { return Single.zip( service.getBadges(user.id()).subscribeOn(Schedulers.io()),__ service.getTags(user.id()).subscribeOn(Schedulers.io()),___ (badges, tags) -> UserStats.create(user, tags, badges) );}_

Page 27: Intro to Retrofit 2 and RxJava2

27

Multi value map

Observable<Observable<Integer>> observable = Observable.just(1, 2, 3).map( i -> Observable.just(i * 10, i * 10 + 1) );

[1, 2, 3] [[10, 11], [20, 21], [30, 31]]

Page 28: Intro to Retrofit 2 and RxJava2
Page 29: Intro to Retrofit 2 and RxJava2

29

map

Observable<Integer> observable = Observable.just(1, 2, 3).flatMap( i -> Observable.just(i * 10, i * 10 + 1) );

[1, 2, 3] [10, 11, 20, 21, 30, 31]

[1, 2, 3] [[10, 11], [20, 21], [30, 31]]

Observable<Observable<Integer>> observable = Observable.just(1, 2, 3).map( i -> Observable.just(i * 10, i * 10 + 1) );

flatMap

Page 30: Intro to Retrofit 2 and RxJava2

30

flatMap

Single<Profile> single = service.login(userName, password) .flatMap(service::getProfile);

Page 31: Intro to Retrofit 2 and RxJava2

31

service.getTopUsers() //1 List<20 User> .map(users -> users.size() > 5 ? users.subList(0, 5) : users) //1 List<5 User>

Page 32: Intro to Retrofit 2 and RxJava2

32

service.getTopUsers() //1 List<20 User> .map(users -> users.size() > 5 ? users.subList(0, 5) : users) //1 List<5 User> .flatMapObservable(users -> Observable.fromIterable(users)) //5 User

Page 33: Intro to Retrofit 2 and RxJava2

33

service.getTopUsers() //1 List<20 User> .map(users -> users.size() > 5 ? users.subList(0, 5) : users) //1 List<5 User> .flattenAsObservable(users -> users) // 5 User

Page 34: Intro to Retrofit 2 and RxJava2

34

service.getTopUsers() //1 List<20 User> .flattenAsObservable(users -> users) // 20 User .take(5) // 5 User

Page 35: Intro to Retrofit 2 and RxJava2

35

service.getTopUsers() //1 List<20 User> .flattenAsObservable(users -> users) // 20 User .take(5) // 5 User .flatMapSingle(user -> loadUserStats(service, user)) // 5 UserStats

Page 36: Intro to Retrofit 2 and RxJava2

36

Single<List<UserStats>> single = service.getTopUsers() //1 List<20 User> .flattenAsObservable(users -> users) // 20 User .take(5) // 5 User .flatMapSingle(user -> loadUserStats(service, user)) // 5 UserStats .toList(); // 1 List<5 UserStats>

Page 37: Intro to Retrofit 2 and RxJava2

37

Single<List<UserStats>> single = service.getTopUsers() //1 List<20 User> .flattenAsObservable(users -> users) // 20 User .take(5) // 5 User .flatMapSingle(user -> loadUserStats(service, user)) // 5 UserStats .toList(); // 1 List<5 UserStats>

single.subscribe( UserStats::printList, Throwable::printStackTrace);

Page 38: Intro to Retrofit 2 and RxJava2

38

730.876 Darin Dimitrov (Sofia, Bulgaria) c# (7.260), asp.net-mvc (6.780), asp.net-mvc-3 (4.629), jquery (3.043), asp.net (3.455) Teacher, Student, Editor, Cleanup, Organizer 724.614 BalusC (Amsterdam, Netherlands) java (6.468), jsf (6.957), jsf-2 (3.809), servlets (2.234), jsp (2.860) php, regex, servlets, java, security 677.074 VonC (France) git (8.555), eclipse (1.715), github (2.417), java (951), version-control (1.075) c, python, php, regex, c# 692.535 Hans Passant (Madison, WI) c# (8.199), .net (4.254), winforms (2.485), c++ (2.084), vb.net (1.457) Tag Editor, Announcer, reference, c, excel 944.295 Jon Skeet (Reading, United Kingdom) c# (18.363), java (10.213), .net (5.338), linq (2.879), string (954) cryptography, reference, c, python, php

Single<List<UserStats>> single = service.getTopUsers() //1 List<20 User> .flattenAsObservable(users -> users) // 20 User .take(5) // 5 User .flatMapSingle(user -> loadUserStats(service, user)) // 5 UserStats .toList(); // 1 List<5 UserStats>

single.subscribe( UserStats::printList, Throwable::printStackTrace);

Page 39: Intro to Retrofit 2 and RxJava2

39

flatMap source code (RxJava1)

public final <R> Observable<R> flatMap( Func1< ? super T, ? extends Observable<? extends R> > func) { return merge(map(func)); }

Page 40: Intro to Retrofit 2 and RxJava2
Page 41: Intro to Retrofit 2 and RxJava2
Page 42: Intro to Retrofit 2 and RxJava2

42

Single<List<UserStats>> single = service.getTopUsers() //1 List<20 User> .flattenAsObservable(users -> users) // 20 User .take(5) // 5 User .concatMapEager(user -> loadUserStats(service, user).toObservable()) // 5 User .toList(); // 1 List<5 UserStats>

single.subscribe( UserStats::printList, Throwable::printStackTrace);

Page 43: Intro to Retrofit 2 and RxJava2

43

944.295 Jon Skeet (Reading, United Kingdom) c# (18.363), java (10.213), .net (5.338), linq (2.879), string (954) cryptography, reference, c, python, php 730.876 Darin Dimitrov (Sofia, Bulgaria) c# (7.260), asp.net-mvc (6.780), asp.net-mvc-3 (4.629), jquery (3.043), asp.net (3.455) Teacher, Student, Editor, Cleanup, Organizer 724.614 BalusC (Amsterdam, Netherlands) java (6.468), jsf (6.957), jsf-2 (3.809), servlets (2.234), jsp (2.860) php, regex, servlets, java, security 692.535 Hans Passant (Madison, WI) c# (8.199), .net (4.254), winforms (2.485), c++ (2.084), vb.net (1.457) Tag Editor, Announcer, reference, c, excel 677.074 VonC (France) git (8.555), eclipse (1.715), github (2.417), java (951), version-control (1.075) c, python, php, regex, c#

Single<List<UserStats>> single = service.getTopUsers() //1 List<20 User> .flattenAsObservable(users -> users) // 20 User .take(5) // 5 User .concatMapEager(user -> loadUserStats(service, user).toObservable()) // 5 User .toList(); // 1 List<5 UserStats>

single.subscribe( UserStats::printList, Throwable::printStackTrace);

Page 44: Intro to Retrofit 2 and RxJava2

44

service.getTopUsers() .flattenAsObservable(users -> users) .take(5) .concatMapEager(user -> Single.zip( service.getBadges(user.id()).subscribeOn(Schedulers.io()), service.getTags(user.id()).subscribeOn(Schedulers.io()), (badges, tags) -> UserStats.create(user, tags, badges) ).toObservable()) .toList() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( UserStats::printList, Throwable::printStackTrace );

Wrapping up

Page 45: Intro to Retrofit 2 and RxJava2

45

This is just the beginning…

Observable class contains more than 400 methods: distinct, debounce, retry, repeat, timeout, …

disposable error management Single, Observable, Flowable, Completable, Maybe hot and cold observable subjects TestScheduler

Page 46: Intro to Retrofit 2 and RxJava2

github.com/fabioCollini/IntroToRetrofit2RxJava2

@fabioCollini linkedin.com/in/fabiocollini github.com/fabioCollini medium.com/@fabioCollini

Thanks for your attention!Questions?