Post on 20-Jan-2017
RxJavaUm pouco sobre programação assíncrona e streams
1
O objetivo dessa apresentação é mostrar um pouco do poder do
RxJava o porque dele ser incrível
2
Quem sou eu• Clêrton Leal
• Nascido e criado em Fortaleza
• Vivendo em Belo Horizonte a pouco mais de 2 meses
• Atualmente trabalhando como consultor para Avenue Code
3
Um pouco de históriaSerá rápido eu prometo =)
4
Reactive Extensions é uma biblioteca, de programação orientada a eventos, desenvolvida pela Microsoft e liberada para o .NET framework em 2011.
Implementa e extende o padrão Observable clássico, porem com um tratamento mais refinado para threads.
5
Em 2012 a Netflix adota o uso de Reactive Extensions para seus módulos escritos em .NET e fica surpresa com a facilidade de programação assíncrona.
Em 2013 a Netflix libera um projeto open source chamado RxJava, uma implementação da especificação RX para Java. Possibilitando assim o uso de RX em todos os seus módulos escritos em Java e Scala.
6
Linguagems
7
• Java: RxJava
• JavaScript: RxJS
• C#: Rx.NET
• C#(Unity): UniRx
• Scala: RxScala
• Clojure: RxClojure
• C++: RxCpp
8
• Ruby: Rx.rb
• Python: RxPY
• Groovy: RxGroovy
• JRuby: RxJRuby
• Kotlin: RxKotlin
• Swift: RxSwift
• PHP: RxPHP
9
Uma sintaxe única para todas as linguagens
10
RxJavaObservable.create(new Observable.OnSubscribe<Integer>() { @Override public void call(Subscriber<? super Integer> observer) { try { for (int i = 1; i < 5; i++) { observer.onNext(i); } observer.onCompleted(); } catch (Exception e) { observer.onError(e); } } } );
11
RxGroovydef myObservable = Observable.create({ aSubscriber -> try { for (int i = 1; i < 5; i++) { aSubscriber.onNext(i); }
aSubscriber.onCompleted(); } catch(Throwable t) { aSubscriber.onError(t); }})
12
RxSwiftlet source = Observable.create { observer in do { for i in 1...5 { observer.on(.Next(i)) }
observer.on(.Completed) } catch { observer.on(.Error) }}
13
Qual a grande jogada do RxJava
14
15
RX trás a união e expansão de dois
padrões de projeto
16
Observable
17
Iterator
18
Observable extendido
19
Adicionando a isso funções de
transformação e tratamento
assíncrono de dados20
Entre o Observable e o Subscriber
podemos aplicar diversas funções de
transformação21
Um pequeno disclaimer sobre Java
8
22
Aplicando um filtroString[] search = {"google", "microsoft"};
Observable.from(search) .filter(s -> s.contains("g")) .subscribe(s -> { Log.d(TAG, s);});
23
24
Vamos adicionar o controle de threads
25
String[] search = {"google", "microsoft"};
Observable.from(search) .filter(s -> complexAndSlowFilter(s)) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(s -> { Log.d(TAG, s);});
26
Schedulers• Schedulers.computation() - Usado para ações em CPU
bound em multi thread.
• Schedulers.io() - Usado para ações em IO bound.
• Schedulers.newThread() - Execução em nova thread.
• Schedulers.immediate() - Execução na thread atual.
• Schedulers.trampoline() - Execução na thread atual, mas apenas após outras ações enfileiradas.
27
SchedulersAndroidSchedulers.mainThread() Main thread de uma aplicação Android.
28
Vamos para um exemplo pratico
29
Em quantas linhas?
• Campo de texto irá buscar em um serviço web
• Buscas feitas apenas com pelo menos 3 caracteres
• Buscas feitas apenas quando o usuário passar 500 milissegundos sem digitar
30
Precisamos criar um observable do SearchViewpublic Observable<String> getSearchObservable(SearchView searchView) { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; }
@Override public boolean onQueryTextChange(String newText) { subscriber.onNext(newText); return true; } }); } }); }
31
E depois aplicar algumas transformaçõespublic Observable<String> getSearchObservable(SearchView searchView) { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; }
@Override public boolean onQueryTextChange(String newText) { subscriber.onNext(newText); return true; } }); } }).filter(s -> fragment != null) .map(s -> "http://search.com.br/" + s) .filter(s -> s.length() >= 3) .debounce(500, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .observeOn(Schedulers.computation());
32
E apenas isso na sua camada de visãogetSearchObservable(searchField).subscribe(s -> { doRequest(); })
33
Vamos ver alguns truques legais com
RxJava
34
Facil de cancelar• Sempre que chamamos o método subscribe(), o retorno do
mesmo é uma Subscription.
• Uma subscription pode ser facilmente cancelada.Subscription subscription = getSearchObservable(searchField).subscribe(s -> { doRequest();});
subscription.unsubscribe();
35
Morte a AsyncTask
36
AsyncTasks são tóxicas para o seu
código.
37
AsyncTask<String, String, User> asyncTask = new AsyncTask<String, String, User>() { @Override protected void onPreExecute() { // Show a progress dialog }
@Override protected User doInBackground(String... params) { return getUserSync(params[0]); }
@Override protected void onPostExecute(User s) { // Update the UI }
@Override protected void onProgressUpdate(String... values) { // Notify progress }};
38
Método getUserpublic Observable<User> getUser(String name) { return Observable.create((Observable.OnSubscribe<User>) subscriber -> { try { User user = getUserSync(name); subscriber.onNext(user); subscriber.onCompleted(); } catch (IOException e) { subscriber.onError(e); } }).subscribeOn(Schedulers.io());}
39
Consumindo getUserprivate void doRequest() { getUser("José") .observeOn(AndroidSchedulers.mainThread()) .subscribe(user -> { updateUi(user); }, throwable -> { handleError(throwable); });}
40
Ou apenas use o Retrofit@GET("/{name}")Observable<User> getUser(@Path("name") String name);
41
Morte a TimerTask
42
Um timer simples com RxJavaSubscription subscription = Observable.timer(START_DELAY, POLL_INTERVAL, TimeUnit.SECONDS) .subscribe(aLong -> { Log.d(TAG, String.valueOf(aLong)); });
subscription.unsubscribe();
43
A simplicidade de fazer tarefas de forma assíncrona abre novas
possibilidades44
Qualquer operação de IO deve ser realizada em uma thread
separada. Isso inclui acesso a banco de dados e
SharedPreferences
45
O maior motivo se adotar RxJava é o
suporte da comunidade
46
Existem muitas bibliotecas com Suporte a RxJava• Retrofit: https://github.com/square/retrofit
• RxBinding: https://github.com/JakeWharton/RxBinding
• SqlBrite: https://github.com/square/sqlbrite
• Rx-preferences: https://github.com/f2prateek/rx-preferences
47
Obrigado =)Contatos
• clertonleal@gmail.com
• clertonleal
48