rxjava+rxandroid (lecture 20 – rx java)

32
RxJava + RxAndroid Android Александр Вайцеховский

Upload: noveo

Post on 16-Apr-2017

316 views

Category:

Education


1 download

TRANSCRIPT

Page 1: RxJava+RxAndroid (Lecture 20 – rx java)

RxJava + RxAndroidAndroid

Александр Вайцеховский

Page 2: RxJava+RxAndroid (Lecture 20 – rx java)

Реактивное программирование

это парадигма программирования, ориентированная на потоки данных

и распространение изменений

© Wikipedia

ООР[еактивное]П

вместо методов и полей — реакцииавтоматическое пересчёт значенийреакции зависят от изменений значений

Page 3: RxJava+RxAndroid (Lecture 20 – rx java)

ReactiveX

Это комбинация лучших идей: паттерн Наблюдатель (Observer), паттерн Перечислитель (Iterator)и функциональное программирование.

1 void hello(String... names) { 2 Observable.from(names).subscribe(new Action1<String>() { 3 @Override 4 public void call(String s) { 5 Log.d("Hello " + s + "!"); 6 } 7 }); 8 } 9 10 hello("Ben", "George", "World");

Output: Hello Ben!

Hello George! Hello World!

Page 4: RxJava+RxAndroid (Lecture 20 – rx java)

Что такое Observable

Объект, предоставляющий асинхронный доступ ко множеству элементов:

Связь с Iterator:

Page 5: RxJava+RxAndroid (Lecture 20 – rx java)

Примитивы RxJava 1 //Наблюдатель 2 interface Observer <T> { 3 void onCompleted(); 4 void onError(Throwable throwable); 5 void onNext(T t); 6 } 7 8 //Объект-наблюдения 9 class Observable <T> { 10 public final static <T> Observable<T> create(OnSubscribe<T> f); 11 public Subscription subscribe(Observer<? super T> observer); 12 } 13 14 //логика оповещения 15 interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {} 16 17 //подписка 18 interface Subscription { 19 public void unsubscribe(); 20 public boolean isUnsubscribed(); 21 } 22 23 abstract class Subscriber<T> implements Observer<T>, Subscription {...}

Page 6: RxJava+RxAndroid (Lecture 20 – rx java)

Создание Observable1 Observable<String> rxHelloWorld = 2 Observable.create(new Observable.OnSubscribe<String>() { 3 @Override 4 public void call(Subscriber<? super String> subscriber) { 5 subscriber.onNext("Hello"); 6 subscriber.onNext("World"); 7 subscriber.onCompleted(); 8 } 9 });

Page 7: RxJava+RxAndroid (Lecture 20 – rx java)

Создание Observable 1 void doWork(final Subscriber<? super String> subscriber) { 2 subscriber.onNext("Hello"); 3 subscriber.onNext("World"); 4 subscriber.onCompleted(); 5 } 6 7 Observable<String> rxHelloWorld = 8 Observable.create(new Observable.OnSubscribe<String>() { 9 @Override10 public void call(Subscriber<? super String> subscriber) { 11 try { 12 doWork(); 13 } catch (Exception ex) { 14 subscriber.onError(ex); 15 } 16 } 17 });

Page 8: RxJava+RxAndroid (Lecture 20 – rx java)

Подписываемся на Observable 1 Subscription subsctiption = rxHelloWorld.subscribe(new Observer<String>() { 2 @Override 3 public void onCompleted() { 4 Log.d("completed"); 5 } 6 7 @Override 8 public void onError(Throwable throwable) { 9 Log.e(throwable); 10 } 11 12 @Override13 public void onNext(String s) { 14 Log.d(s); 15 } 16 });

Hello World

Completed

Page 9: RxJava+RxAndroid (Lecture 20 – rx java)

Потоки и Observable

Предоставляет методы:

observeOn(Thread) - поток, в котором выполнять логику налюдаемого объектаsubscribeOn(Thread) - поток, в котором будут вызываться методы подписчика

Page 10: RxJava+RxAndroid (Lecture 20 – rx java)

Потоки и Observable

Page 11: RxJava+RxAndroid (Lecture 20 – rx java)

Трансформации 1 Observable<Integer> toLength(Observable<String> source){ 2 return source.map(new Func1<String, Integer>() { 3 @Override 4 public Integer call(String s) { 5 return s.length(); 6 } 7 }); 8 } 9 10 toLength(rxHelloWorld).subscribe(new Observer<Integer>() { 11 @Override 12 public void onCompleted() { Log.d("completed"); } 13 14 @Override 15 public void onError(Throwable throwable) { Log.e(throwable); } 16 17 @Override 18 public void onNext(Integer i) { Log.d(String.format("length: %d", i)); } 19 });

length: 5 length: 5 completed

Page 12: RxJava+RxAndroid (Lecture 20 – rx java)

Может быть красиво

Java7

1 rxHelloWorld.map(new Func1<String, Integer>() { 2 @Override3 public Integer call(String s) { 4 return s.length(); 5 } 6 });

Java8

1 rxHelloWorld.map((String s) -> { // 2 return s.length(); //можно так! 3 }); // 4 rxHelloWorld.map((String s) -> s.length()); //или так 5 rxHelloWorld.map((s) -> s.length()); //или упростить 6 rxHelloWorld.map(s -> s.length()); //или совсем просто 7 rxHelloWorld.map(String::length); //o_O

* Но Android не поддерживает Java8:( ** Зато есть Retrolambda

Page 13: RxJava+RxAndroid (Lecture 20 – rx java)

Обычная логика

Page 14: RxJava+RxAndroid (Lecture 20 – rx java)

Реактивная логика

Page 15: RxJava+RxAndroid (Lecture 20 – rx java)

Упрощенное создание

Create - создать обычный ObservableJust - создает Observable из Объекта (его и возвращает)From - создает Observable из Array, Iterable, FutureEmpty, Never, Throw - на каждый метод подписчикаTimer, Interval - созданный периодичный ObservableRepeat - Observable, который возвращает одно и то же

Page 16: RxJava+RxAndroid (Lecture 20 – rx java)

Другие операторы

Трансформация

Map - преобразовывает возвращаемоезначениеFlatMap - преобразовывает значение врезультат другого ObservableBuffer - возвращает комбинации значенийWindow, Scan, GroupBy...

Комбинирование

CombineLatest - возвращает самыепоследние значения исходных ObservableMerge - объединяет возвращаемыезначенияZip - объединяет каждое и возвращаетрезультат объединения

Математические операции

Max, Min - ждет конца, возвращает нужноеSum, Reduce - применяет функцию последовательно

Page 17: RxJava+RxAndroid (Lecture 20 – rx java)

Marble diagram

RxJava wiki для объяснение каждого оператора использует Marble Diagram

Page 18: RxJava+RxAndroid (Lecture 20 – rx java)

Merge и Zip

Page 19: RxJava+RxAndroid (Lecture 20 – rx java)

Map и FlatMap

Page 20: RxJava+RxAndroid (Lecture 20 – rx java)

Filter и Debounce

Page 21: RxJava+RxAndroid (Lecture 20 – rx java)

Примеры

Page 22: RxJava+RxAndroid (Lecture 20 – rx java)

Async 1 Observable 2 .create((Subscriber<? super Bitmap> subscriber) -> { 3 try{ 4 Bitmap image = loadImage(); 5 subscriber.onNext(image); 6 subscriber.onCompleted(); 7 } catch (Exception ex) { 8 subscriber.onError(ex); 9 } 10 }) 11 .subscribeOn(Schedulers.io()) 12 .subscribe(() -> toast("loaded"));

Page 23: RxJava+RxAndroid (Lecture 20 – rx java)

View click 1 public static <T extends View> Observable<T> clicksFrom(T view) { 2 PublishSubject publishSubject = PublishSubject.create(); 3 view.setOnClickListener(new OnClickListener() { 4 @Override 5 public void onClick(View view) { 6 publishSubject.onNext(view)); 7 } 8 }); 9 return publishSubject.asObservable(); 10 } 11 clicksFrom(button).subscribe(view -> toast("clicked"));

Page 24: RxJava+RxAndroid (Lecture 20 – rx java)

Несколько событий 1 final ImageView imageView = (ImageView) findViewById(R.id.image); 2 3 Observable<Bitmap> imageObservable = 4 loadImage() 5 .cache() 6 .observeOn(AndroidSchedulers.mainThread()); 7 8 9 imageObservable.subscribe((Bitmap image) -> imageView.setImageBitmap(image));10 imageObservable 11 .flatMap(image -> { 12 clicksFrom(imageView).map((ImageView view) -> image) 13 }) 14 .subscribe((Bitmap image) -> processImage(image));

Что здесь происходит?Когда будет вызван setImageBitmap?Когда будет вызван processImage?

Page 25: RxJava+RxAndroid (Lecture 20 – rx java)

Гамбургер

Page 26: RxJava+RxAndroid (Lecture 20 – rx java)

Поддержка Retro�t 1 class SimpleProfile { 2 private int id; 3 public String getId() {return id;} 4 } 5 6 class Network { 7 @GET("/users") 8 Observable<List<SimpleProfile>> getUsers(); 9 10 @GET("/users/{id}") 11 Observable<ProfileDetails> getUser(@Path("id") int id); 12 } 13 14 network.getUsers() 15 .flatMap((List<SimpleProfile> list) -> Observable.from(list)) 16 .flatMap((SimpleProfile profile) -> api.getUser(profile.getId())) 17 //.filter((ProfileDetails details) -> details.getSex() == Sex.FEMALE) 18 //.take(5)19 //.doOnNext((ProfileDetails details) -> saveToDatabase(details)) 20 .subscribe((ProfileDetails details) -> handleProfile(details));

Page 27: RxJava+RxAndroid (Lecture 20 – rx java)

Обработка ошибок! 1 showProgressBar(); 2 network.getUsers() 3 .flatMap(Observable::from) 4 .subscribe(new Subscriber<String>() { 5 @Override 6 public void onNext(String user) { 7 listAdapter.add(user); 8 } 9 10 @Override11 public void onCompleted() { 12 hideProgerssBar(); 13 showListView();14 } 15 16 @Override17 public void onError(Throwable e) { 18 hideProgerssBar(); 19 hideListView(); 20 showErrorView(); 21 } 22 });

Page 28: RxJava+RxAndroid (Lecture 20 – rx java)

RxAndroid1. Удобная работу с потоками2. Работа с Android Lifecycle - RxLifecycle3. Работа с View - RxBinding4. SqlBrite - обертка над базой5. и еще RxLocation / RxPermissions / RxNoti�cation

Page 29: RxJava+RxAndroid (Lecture 20 – rx java)

RxAndroid - Threads

Main Thread

1 Observable.just("one", "two", "three", "four", "five") 2 .subscribeOn(Schedulers.newThread()) 3 .observeOn(AndroidSchedulers.mainThread());

Handler Thread

1 final Handler handler = new Handler(); // bound to this thread 2 Observable.just("one", "two", "three", "four", "five") 3 .subscribeOn(Schedulers.newThread()) 4 .observeOn(AndroidSchedulers.handlerThread(handler));

Page 30: RxJava+RxAndroid (Lecture 20 – rx java)

RxLifecycle

Bindings

1 IntentFilter intentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION) 2 RxBroadcastReceiver.create(context, intentFilter)

Page 31: RxJava+RxAndroid (Lecture 20 – rx java)

RxBinding

clicks - обработка нажатий

1 ViewObservable.clicks(mCardNameEditText, /*emit initial value*/ false) 2 .subscribe((View view) -> handleClick(view));

text - обработка ввода текста

1 ViewObservable.text(editTextName, false) 2 .subscribe((EditText editText) -> handleText(editText.getText())));

input - обработка "чекбоксов"

1 ViewObservable.input(compoundButton, false) 2 .subscribe((Boolean value) -> changeState(value));

Page 32: RxJava+RxAndroid (Lecture 20 – rx java)

Полезные ссылки

ReactiveXRxJavaRxAndroidGrokking RxJava, part 1 ищите там же части 2, 3, 4

..или перевод на русскийFRP on Android