Programación Reactiva en Android

4,257 views

Published on

Ponencia ofrecida por Oier Blasco en DroidconMAD2013. Sinopsis: La programación reactiva es un paradigma de programación que se centra en los flujos de datos. La presentación trata de cómo podemos usar la programación reactiva para simplificar la programación de tareas asíncronas en android (principalmente las aplicaciones que consumen datos de servicios remotos). Para ello comenzaremos la presentación con una introducción sobre los motivos y los fundamentos de la programación reactiva y como los implementa RxJava (El port open-source hecho por Netflix de la Rx extensions de microsoft). El la segunda para parte de la presentación veremos algunos ejemplos concreto de cómo podemos aplicar estos principios a problemas cotidianos en android.

Published in: Technology
  • Be the first to comment

Programación Reactiva en Android

  1. 1. Programación Reactiva en Android Oier Blasco Linares ! @oier! Diciembre 2013
  2. 2. Contenido • Limitaciones de los componentes android.! • Introducción a RxJava.! • Concurrencia.! • Pros y Contras.! • Preguntas.
  3. 3. Limitaciones de los componentes Android
  4. 4. Intent Service • No especifica como notificar a los clientes.! • Ningún controlo sobre la concurrencia.! • No especifican método de gestión de errores.
  5. 5. 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.
  6. 6. Programación reactiva
  7. 7. 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
  8. 8. Programación imperativa ejemplo X = 10;! y = x + 5;! X= 20! Cual es el valor de Y? 15
  9. 9. Programación reactiva ejemplo X = 10;! Func<int> y = () -> {x + 5};! X= 20! Cual es el valor de Y? 25
  10. 10. RX JAVA
  11. 11. 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.
  12. 12. Observable • Una secuencia de valores , finita o infinita.! • Permite la subscripción de observer mediante el método subscribe.! • Lazy evaluation.!
  13. 13. 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.! !
  14. 14. 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!!!!!”); } }
  15. 15. Observable Observable.create( new Observable.OnSubscribeFunc<String>() { ! public Subscription onSubscribe(Observer<? super String> observer) { observer.onNext("pedro@domain.com"); observer.onNext("maria@domain.com"); observer.onNext("juan@domain.com"); observer.onNext("isa@domain.com"); ! observer.onCompleted(); ! return Subscriptions.empty(); } ! });
  16. 16. Composición
  17. 17. 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. !
  18. 18. Observer de ejemplo 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) } }; }
  19. 19. Map Transforma la secuencia mediante la función 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!
  20. 20. MapMany Combina n secuencias mediante la función 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); Output: [AAPL-> 25,730120]! [GOOG -> 23,464752]! [GOOG -> 11,255009]! Sequence complete
  21. 21. Reduce Aplica una función a cada item devolviendo únicamente el acumulado 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); Output: 15! Sequence complete
  22. 22. Filter Filtra la secuencia en base a la función suministrada 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); Output: 2! 4! 6! 8! Sequence complete
  23. 23. SkipWhile No emite los valores hasta que una condición se cumple 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); Output: 4! 5! 4! 3! 2! 1! Sequence complete
  24. 24. Take Emite solo los N elementos de la lista 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); Output: 1! 2! Sequence complete
  25. 25. Distinct Elimina los duplicados de la secuencia 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); Output: 1! 2! 3! 4! Sequence complete
  26. 26. Merge Fusiona n secuencias 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); Output: 1! 3! 2! 5! 4! 7! 6! Sequence complete
  27. 27. Zip Combina n secuencias mediante la función ! 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); Output: [1, 2]! [3, 4]! [5, 6]! Sequence complete
  28. 28. Concurrencia
  29. 29. 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, …
  30. 30. 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()); } }
  31. 31. 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) { }}); … }
  32. 32. 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.!
  33. 33. Contras • Curva de aprendizaje.! • Sintaxis de java 6 ( Java 8 lo mejora pero no esta disponible para programación en android).

×