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

Programación Reactiva en Android

Avatar for oier blasco oier blasco
December 08, 2013

Programación Reactiva en Android

Avatar for oier blasco

oier blasco

December 08, 2013

Other Decks in Technology

Transcript

  1. Contenido • Limitaciones de los componentes android.! • Introducción a

    RxJava.! • Concurrencia.! • Pros y Contras.! • Preguntas.
  2. Intent Service • No especifica como notificar a los clientes.!

    • Ningún controlo sobre la concurrencia.! • No especifican método de gestión de errores.
  3. AsyncTask • Implementación cambia dependiendo del la version de android.!

    • En la version actual se ejecutan en serie.! • Suelen ser fuente de context leak.! • No especifican método de gestión de errores/excepciones.
  4. Programación reativa Definición “La programación reactiva es un paradigma de

    programación orientado a flujos de datos y a la propagación de cambios. “ Wikipedia
  5. Programación imperativa ejemplo X = 10;! y = x +

    5;! X= 20! Cual es el valor de Y? 15
  6. Programación reactiva ejemplo X = 10;! Func<int> y = ()

    -> {x + 5};! X= 20! Cual es el valor de Y? 25
  7. RxJava • Una librería para componer programas asíncronos y basados

    en evento mediante el uso de secuencias observables.! • Open source.! • Creada por Netflix.! • Un port de “Reactive extension” creadas por Microsoft.! • Observable / Observer como elementos basicos.
  8. Observable • Una secuencia de valores , finita o infinita.!

    • Permite la subscripción de observer mediante el método subscribe.! • Lazy evaluation.!
  9. Observer • Extension del patron observer de GoF.! • Se

    subscribe a objectos que implemente el interfaz Observable y reacciona a lo items que este emita.! • El observer “espera” de manera no bloquean los valores emitidos por el Observable.! !
  10. Observer Observer<String> stringObserver = new Observer<String> { ! public void

    onNext(String value) { System.out.println(“ NextValue : ” + value); } public void onCompleted() { System.out.println(“Done!”); } public void onError(Throwable t) { System.out.println(“ERROR!!!!!”); } }
  11. Observable Observable.create( new Observable.OnSubscribeFunc<String>() { ! public Subscription onSubscribe(Observer<? super

    String> observer) { observer.onNext("[email protected]"); observer.onNext("[email protected]"); observer.onNext("[email protected]"); observer.onNext("[email protected]"); ! observer.onCompleted(); ! return Subscriptions.empty(); } ! });
  12. Composición • Los Observables pueden modificados mediante operadores.! • Estos

    operadores permiten filtrar , combinar y transformar las secuencias representadas por los Observables.! • Los operadores retornan otros observables con lo cual se pueden concatenar para producir la secuencia de datos deseada.! • RxJava viene con más de 50 operadores.! • Es posible crear mas operadores para ajustarlos a nuestras necesidades.! • Los “Marble diagrams” se usan en la documentación de RxJava para explicar el funcionamiento de los operadores de una forma gráfica. !
  13. private static Observer<Integer> createIntegerObserver(){ return new Observer<Integer>() { ! public

    void onCompleted() { System.out.println("Sequence complete"); } ! public void onError(Throwable throwable) { String msg = throwable.getMessage(); System.out.println("Error: “+ msg); } ! public void onNext(Integer i) { System.out.println(i) } }; } Observer de ejemplo
  14. Map Integer[] values = new Integer[]{1, 2, 3, 4, 5};

    Observable<Integer> numbers = Observable.from(values); ! numbers.map(new Func1<Integer, Integer>() { public Integer call(Integer i) { return i * i; } }).subscribe(observer); Output: 1! 4! 9! 16! 25! Transforma la secuencia mediante la función
  15. MapMany Observable<String> myStockSymbols = StocksService.myPortfolio(); Observer<StockInfo> stockInfoObserver = createStockInfoObserver(); !

    myStockSymbols.mapMany(new Func1<String, Observable<StockInfo>>() { public Observable<StockInfo> call(String stockSymbol) { return StocksService.getLastQuotes(stockSymbol); } ! }).subscribe(stockInfoObserver); [AAPL -> 25,730120]! [GOOG -> 23,464752]! [GOOG -> 11,255009]! Sequence complete Output: Combina n secuencias mediante la función
  16. Reduce Integer[] values = new Integer[]{1, 2, 3, 4, 5};

    Observable<Integer> numbers = Observable.from(values); Observer<Integer> observer = createIntegerObserver(); ! numbers.reduce(new Func2<Integer, Integer, Integer>() { public Integer call(Integer a , Integer b) { return a + b; } }).subscribe(observer); 15! Sequence complete Output: Aplica una función a cada item devolviendo únicamente el acumulado
  17. Filter Integer[] values = new Integer[]{1, 2, 3, 4, 5,

    6, 7, 8, 9}; Observable<Integer> numbers = Observable.from(values); Observer<Integer> observer = createIntegerObserver(); ! numbers.filter(new Func1<Integer, Boolean>() { public Boolean call(Integer i) { return (i % 2 == 0); } }).subscribe(observer); 2! 4! 6! 8! Sequence complete Output: Filtra la secuencia en base a la función suministrada
  18. SkipWhile Integer[] values = new Integer[]{1, 2, 3, 4, 5,

    4, 3, 2, 1}; Observable<Integer> numbers = Observable.from(values); ! Observer<Integer> observer = createIntegerObserver(); numbers.skipWhile(new Func1<Integer, Boolean>() { public Boolean call(Integer i) { return (i <4); } }).subscribe(observer); 4! 5! 4! 3! 2! 1! Sequence complete Output: No emite los valores hasta que una condición se cumple
  19. Take Integer[] values = new Integer[]{1, 2, 3, 4, 5,

    4, 3, 2, 1}; Observable<Integer> numbers = Observable.from(values); ! Observer<Integer> observer = createIntegerObserver(); numbers.take(2).subscribe(observer); 1! 2! Sequence complete Output: Emite solo los N elementos de la lista
  20. Distinct Integer[] values = new Integer[]{1, 2, 1, 2, 3,

    3, 4, 1, 2}; Observable<Integer> numbers = Observable.from(values); Observer<Integer> observer =createIntegerObserver(); ! numbers.distinct().subscribe(observer); 1! 2! 3! 4! Sequence complete Output: Elimina los duplicados de la secuencia
  21. Merge Observable<Integer> odds = Observable.from(new Integer[]{1, 3, 5, 7}); Observable<Integer>

    evens = Observable.from(new Integer[]{2,4,6}); Observer<Integer> observer = createIntegerObserver(); Observable.merge(odds,evens).subscribe(observer); 1! 3! 2! 5! 4! 7! 6! Sequence complete Output: Fusiona n secuencias
  22. Zip Observable<Integer> odds = Observable.from(new Integer[]{1, 3, 5, 7}); Observable<Integer>

    evens = Observable.from(new Integer[]{2,4,6}); Observer<String> observer = createStringObserver(); Observable.zip(odds,evens ,new Func2<Integer, Integer, String>() { public String call(Integer a, Integer b) { return String.format("[%s,%s]",a,b); } ! }).subscribe(observer); [1, 2]! [3, 4]! [5, 6]! Sequence complete Output: Combina n secuencias mediante la función
  23. Schedulers • Los observables son mono hilo (single threaded) por

    defecto.! • Los scheduler se usan para introducir la concurrencia permitiendo ejecutar partes de nuestro cadena de observables concurrentemente.! • Hay dos aspectos de nuestros Observables de los que queremos poder controlar la concurrencia:! • En la invocación de la subscripción. Para ello usaremos el método Observable.observeOn(Scheduler s).! • En las notificaciones al Observer. Para ello usaremos el método Observable.notifyOn(Scheduler s).! • Hay varia implementaciones de los schedulers. Ex: CurrentThreadScheduler, ExecutorScheduler, NewThreadScheduler, …
  24. Schedulers - Ejemplo public class WeatherAPI ! public static Observable<WeatherData>

    getWeatherFromCities(String ... cities){ return Observable.from(cities).map(new Func1<String,WeatherData>() { public WeatherData call(String s) { // Call to remote api return RemoteService.getWeatherData(s); } }).subscribeOn(Schedulers.threadPoolForIO()); } }
  25. Schedulers - Ejemplo String [] cities= { "Madrid","Barcelona","Bilbao"} ; WeatherAPI.getWeatherFromCities(cities)

    .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<WeatherData>() { // Safe to call UI code from here public void onCompleted() { … } public void onError(Throwable throwable) { … } public void onNext(String s) { … } }});
  26. Pros • Método simple y uniforme de tratar los eventos

    y los errores (onNext, onError,onCompleted).! • Podemos crea APIS que mantengan el control sobre la concurrencia .! • Facilmente Testeable.! • Reusable permite que el cliente extienda/adapte la secuencia usando los operadores.!
  27. Contras • Curva de aprendizaje.! • Sintaxis de java 6

    ( Java 8 lo mejora pero no esta disponible para programación en android).