Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Intro a RxJava

Intro a RxJava

Charla introductoria a RxJava, sin entrar en mucho detalle, intento acercar la programación reactiva de un modo ameno y sencillo.

Antonio Nicolás Pina

December 13, 2016
Tweet

More Decks by Antonio Nicolás Pina

Other Decks in Programming

Transcript

  1. Intro a RxJava Antonio Nicolás Pina Android & Go developer

    @anpez https://www.anpez.es Murcia Android Developers S02E01 13 diciembre 2016
  2. Programación reactiva ▣ Orientada a flujos de datos. Casos típicos:

    □ Entrada del teclado □ Red □ Base de datos ▣ Desacopla la fuente de los datos de los receptores. □ Evita el uso de listeners que acoplan el código.
  3. Programación funcional ▣ Orientada a funciones matemáticas. ▣ Reutilización de

    funciones existentes. ▣ Composición de funciones sencillas. ▣ Filosofía UNIX.
  4. ‘’ Make each program do one thing well. To do

    a new job, build afresh rather than complicate old programs by adding new "features". Doug McIlroy The Bell System Technical Journal 1978
  5. Programación funcional reactiva ▣ Introducida en 1997 ▣ Combina los

    dos modelos anteriores ▣ Nos permite manejar cadenas de datos o “eventos”, aplicando funciones (operadores) sobre los mismos. ▣ RxJava se basa en los Observables de .NET 4 (año 2010).
  6. Observable<T> ▣ Interfaz que define la “fuente” de los datos.

    ▣ Sólo un método: OnSubscribe. ▣ Decenas de implementaciones.
  7. Observer<T> ▣ Define una única interfaz común para todos los

    objetos que se suscriben a Observables. ▣ Dispone de tres métodos: □ onNext() Llamada con cada elemento emitido. □ onError() Para situaciones de error. □ onCompleted() El procesamiento acabó correctamente.
  8. Observer<T> ▣ Se podría esquematizar así. try { for(Elem e:

    sequence) { observer.onNext(e); } observer.onCompleted(); } catch (Exception e) { observer.onError(); }
  9. Creación de Observable<T> ▣ La creación se hace (preferentemente) a

    través de métodos estáticos de Observable. □ Observable.just(elemento) □ Observable.just(elemento 1, elemento 2, ...) □ Observable.from(iterable) □ Observable.interval(3, TimeUnit.SECONDS)
  10. Operadores sobre el stream ▣ Hay cientos de operadores aplicables

    sobre un stream. ▣ Se pueden definir operadores propios, aunque es un caso poco habitual. ▣ Con ellos, podemos: □ Modificar eventos del stream y reemitir la versión modificada. □ Filtrar elementos, para que no continúen downstream. □ Combinar elementos. □ ¡Multithreading!
  11. Operadores sobre el stream ▣ Casi cualquier cosa que se

    te ocurra, se puede hacer combinando operadores. flatmapthatshit.com
  12. Operadores sobre el stream ▣ Hay cientos de operadores aplicables

    sobre un stream. ▣ Se pueden definir operadores propios, aunque es un caso poco habitual. ▣ Con ellos, podemos: □ Modificar eventos del stream y reemitir la versión modificada. □ Filtrar elementos, para que no continúen downstream. □ Combinar elementos. □ ¡Multithreading!
  13. Una nota sobre funciones lambda ▣ RxJava funciona sobre Java6,

    es decir, Android 2.3. ▣ Java no soporta funciones lambda hasta Java 8. ▣ Para ello, yo utilizo Retrolambda, que permite utilizar dichas funciones compiladas con bytecode Java 6.
  14. Código para Java 6 Observable.just("http://example.com/image.jpg") .map(new Func1<String, Bitmap>() { @Override

    public Bitmap call(String url) { return loader.load(url); } }) .subscribe(...)
  15. Cuidado! ▣ Bytecode de la versión lambda iconst_1 invokestatic java/lang/Integer

    valueOf((I)Ljava/lang/Integer;); invokestatic rx/Observable just((Ljava/lang/Object;)Lrx/Observable;); invokedynamic call(rx.functions.Func1); .map(x -> x*x)
  16. Cuidado! ▣ Bytecode de la versión con new Func1 iconst_1

    invokestatic java/lang/Integer valueOf((I)Ljava/lang/Integer;); invokestatic rx/Observable just((Ljava/lang/Object;)Lrx/Observable;); new anpez/Test$1 dup aload0 // reference to self invokespecial anpez/Test$1 <init>((Lanpez/Test;)V); .map(x -> x*x)
  17. subscribeOn vs observeOn ▣ Estos dos operadores especiales se utilizan

    para indicar a RxJava en qué hilos se ha de ejecutar cada paso. ▣ subscribeOn() indica en qué hilo se han de emitir los eventos. ▣ observeOn() especifica en qué hilo se ejecuta el .onNext(). ▣ Por defecto, todo ocurre en el mismo hilo en que se suscribe el Observer.
  18. Un ejemplo completo (I) ▣ En este ejemplo cargamos una

    imagen de red. Observable.just(url) .map(url -> loader.load(url)) .subscribe(ImageView::setBitmap);
  19. Un ejemplo completo (II) ▣ Ahora la carga se produce

    en un hilo de I/O. Observable.just(url) .map(url -> loader.load(url)) .subscribeOn(Schedulers.io()) .subscribe(ImageView::setBitmap);
  20. Un ejemplo completo (y III) ▣ De este modo, la

    vista se toca en el hilo correcto. Observable.just(url) .map(url -> loader.load(url)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(ImageView::setBitmap);
  21. Chisme for Sensu Ejemplos extraídos de la última aplicación que

    he desarrollado utilizando RxJava: un cliente para Sensu
  22. Retrofit ▣ Con Retrofit podemos obtener un Observable a partir

    de una llamada. public interface ChecksService { @GET("checks") Observable<List<Check>> all(); @POST("request") Observable<IssueResponse> issue(@Body Map<String, Object> body); }
  23. Retrofit ▣ Y podemos aplicarle los operadores que queramos para

    transformar el resultado. public Observable<Date> issue(Check check) { Map<String, Object> params = new HashMap<>(); params.put("check", check.name()); return checksService.issue(params) .map(IssueResponse::issued) .map(time -> time*1000) .map(Date::new); }
  24. RxBinding ▣ Librería de Jake Wharton para utilizar RxJava sobre

    vistas de Android. ▣ Elimina la necesidad de utilizar listeners. ▣ Simplifica operaciones muy comunes. RxTextView.textChanges(hostTextView) .subscribe(this::checkHost);
  25. @Mock HostsRepository hostsRepository; Host host = new Host(1, "[email protected]", "https",

    "test.com", 443, "user", "pass"); when(hostsRepository .all()) .thenReturn(Observable.just(host)); Test! ▣ RxJava también te ayuda a escribir tests. ▣ Utilizando Espresso con Mockito, es muy fácil mockear un método que devuelve un Observable.
  26. Observable.just(drawerBuilder) .subscribeOn(Schedulers.computation()) .observeOn(Schedulers.computation()) ... // Build drawer on background .observeOn(AndroidSchedulers.mainThread())

    .subscribe(builder -> { drawer = builder.build(); mainViewModel.initialize(); }); Whatever! ▣ Lo utilizo casi para cualquier cosa.
  27. Gotchas ▣ Es muy importante definir un .doOnError() que recoja

    los posibles errores. ▣ Los Observers deben poder procesar eventos más rápido de lo que los emiten los Observables (Backpressure). □ No suele ser un problema, hasta que intentamos hacer algo avanzado. ▣ NO utilizar Observable.create(). Si usamos RxJava2, utilizar Flowable.create().
  28. Gotchas ▣ No usarlo ciegamente, implica una penalización de rendimiento.

    ▣ La documentación a veces no es demasiado clara. □ Los comentarios de StackOverflow tampoco suelen ayudar mucho. ▣ Los tutoriales que verás, suelen utilizar incorrectamente Observable.create().
  29. Conclusiones ▣ Se puede usar RxJava para reemplazar completamente las

    AsyncTask. ▣ Por norma general, se puede usar RxJava (via RxBinding o hecho por nosotros mismos), en lugar de Listeners. ▣ Para tareas de entrada/salida o de computación es perfecto, ya que la sobrecarga es mínima en este caso.
  30. Credits Special thanks to all the people who made and

    released these awesome resources for free: ▣ Presentation template by SlidesCarnival