Top Banner
Sviluppare app event-driven con RxJava su Android Rx
35

Sviluppare app event-driven con RxJava su Android

Jan 19, 2017

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Sviluppare app event-driven con RxJava su Android

Sviluppare app event-driven con RxJava su Android

Rx

Page 2: Sviluppare app event-driven con RxJava su Android

Boris D’AmatoAndroid Developer @

+BorisDAmato

@borisdamato

damatoboris

borisdamato

Page 3: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Il Problema

Page 4: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Il Problema

UI Thread

Main Thread

Page 5: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

La Soluzione

RxJava RxJava è un’implementazione delle Reactive Extensions per la Java VM

Una libreria per realizzare programmi asincroni ed event-based utilizzando sequenze di

observable.

Page 6: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Cosa significa “Reactive”?Un sistema Reattivo deve essere

ovvero

alle richieste degli utenti

a guasti ed errori

Responsivo Resiliente Elastico Orientato a messaggi

al carico di lavoro a eventi e messaggi

reagire

Page 7: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Reactive Programming

Erik Meijer Ben Christensen

Rx.Net RxJava

Dávid Karnok

RxJava

Page 8: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Reactive Programming

“Paradigma di programmazione basato su flussi di dati e propagazione dei cambiamenti” [Wikipedia]

Data flow Observer pattern Push vs Pull

Page 9: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Gli Attori

Observable Observer Subscriber Subject

Generatore di dati

Reagisce alla ricezione dei dati

Ibrido tra Observable e

Observer

Page 10: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Comunicazione Observable - Observer

Observer

subscribe

Observable

onNext()

onComplete()

onError()

onSubscribe()

Page 11: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Android Time!

RecyclerView

Lista dei contatti

Page 12: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Creazione di un Observableprivate Observable<String> getContacts() { return Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { List<String> contacts = new ArrayList<>();

Cursor cursor = [...];while (cursor.moveToNext()) {

String displayName = [...]; contacts.add(displayName);

}cursor.close();

for (String contact : contacts) { if (e.isDisposed()) return; e.onNext(contact); } if (!e.isDisposed()) e.onComplete();}});}

onError(Throwable e)

onNext(T item)

onComplete()

Page 13: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Creazione di un Observable

List<Contact> contacts = [...];Observable.fromArray(contacts).subscribe([...]);

Observable.just()

.fromIterable().fromFuture()

.fromCallable()

.fromPublisher()

Observable.fromArray()

List<Contact> contacts = [...];Observable.just(contacts.get(0), contacts.get(1))

.subscribe([...]);

Page 14: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Creazione di un Observable

Observable.empty() Observable.never() Observable.throw()

Page 15: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Observer<Contact> observer = new Observer<Contact>() { @Override public void onSubscribe(Disposable d) { Log.d(TAG, "onSubscribe");

Log.d(TAG, "isDisposed: " + d.isDisposed()); }

@Override public void onNext(Contact item) { Log.d(TAG, "onNext"); adapter.addItem(item); }

@Override public void onError(Throwable e) { Log.e(TAG, "onError: " + e.getMessage); }

@Override public void onComplete() { Log.d(TAG, "onComplete"); }};

Subscribe

List<Contact> contacts = [...];Observable.fromArray(contacts)

.subscribe(observer);

Page 16: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

Giorgio Carlo Andrea Gianni

Giorgio Gianni

getContacts().filter(new Predicate<Contact>() { @Override public boolean test(Contact contact) throws Exception { return contact.getName().startsWith("G"); }})

Filter

Page 17: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering (Lambda Version)

Giorgio Carlo Andrea Gianni

Giorgio Gianni

getContacts().filter(contact -> contact.getName().startsWith("G"))Filter

https://github.com/evant/gradle-retrolambda

Page 18: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

Giorgio Carlo Andrea Gianni

Giorgio

getContacts().take(3)Take

Carlo Andrea

Page 19: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

Giorgio Carlo Andrea Gianni

getContacts().takeLast(3)TakeLast

Carlo Andrea Gianni

Page 20: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

Giorgio Carlo Giorgio Gianni

getContacts().distinct()Distinct

Carlo GianniGiorgio

Page 21: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

21

getTemperature().distinct()

21 20 19 20 21 22 23 23 21 22 21

21 20 19 22 23

Distinct

Page 22: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

21

getTemperature().distinctUntilChanged()

21 20 19 20 21 22 23 23 21 22 21

DistinctUntil

Changed

21 20 19 20 21 22 23 21 22 21

Page 23: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

21

getTemperature().sample(30, TimeUnit.SECONDS)

21 20 19 20 21 22 23 23 21 22 21

Sampleo

ThrottleLast

20 21

30 sec 30 sec

Page 24: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Filtering

21

getTemperature().throttleFirst(30, TimeUnit.SECONDS)

21 20 19 20 21 22 23 23 21 22 21

ThrottleFirst

30 sec 30 sec

21 21 22

Page 25: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Transforming

Giorgio Carlo Andrea Gianni

giorgio

getContacts().map((contact) -> {contact.setName(

contact.getName().toLowerCase());return contact;

})

Map

carlo andrea gianni

Page 26: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Combining

Giorgio Carlo Andrea Gianni

Giorgio

Observable.merge(getContacts(), getImportingContacts())Merge

Carlo Andrea Gianni

Marco Francesco

Marco Francesco

Page 27: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Combining

21° 22° 20° 18°

21° - 17:30

Zip

17:30 18:00 18:30 19:00

16°

22° - 18:00 20° - 18:30 18° - 19:00

Observable.zip(getTemperature(), getTime(), this::updateMonitor)

Page 28: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Torniamo ad Android...private Observable<Contact> getContacts() { return Observable.create(new ObservableOnSubscribe<Contact>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { List<String> contacts = new ArrayList<>();

SharedPreferences prefs = getActivity().getPreferences(Context.MOODE_PRIVATE);Type contactType = new TypeToken<List<Contact>>(){}.getType();String contactsGson = prefs.getString(“CONTACTS”, “”);

if (!contactsGson.isEmpty())contacts = new Gson().fromJson(contactsGson, contactType);

for (Contact contact : contacts) {e.onNext(contact);

} if (!e.isDisposed()) e.onComplete();}});}

Page 29: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

… e accade questo...

D/StrictMode: StrictMode policy violation; ~duration=253 ms: android.os.StrictMode$ StrictModeDiskReadViolation: policy=31violation=2 at android.os.StrictMode $AndroidBlockGuardPolicy. onReadFromDisk(StrictMode.java:1135)

Page 30: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

SoluzionegetContacts()

.subscribeOn( Schedulers.io() )

.subscribe([...]);

Schedulers.

computation()

io()

immediate()

newThread()

trampoline()

Page 31: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

… altro problema

android.view.ViewRoot$CalledFromWrongThreadException:

Only the original thread that created a view hierarchy can touch its views.

getContacts().subscribeOn(Schedulers.io()).observeOn( AndroidSchedulers.mainThread() ).subscribe([...]);

Soluzione

Page 32: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Nella pratica

● La ricerca debba essere eseguita ogni 500 millisecondi

Vogliamo che:

● La ricerca debba partire solo dopo che sia stati inseriti almeno 3 caratteri

Page 33: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

RxBinding

compile 'com.jakewharton.rxbinding:rxbinding:0.4.0'compile 'com.jakewharton.rxbinding:rxbinding-support-v4:0.4.0'compile 'com.jakewharton.rxbinding:rxbinding-design:0.4.0'

[ . . .]

https://github.com/JakeWharton/RxBinding

Page 34: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Nella pratica

RxTextView.textChanges(searchField).debounce(500, TimeUnit.MILLISECONDS).filter( (charSequence) -> return charSequence.length() >= 3 ).subscribe( [...] )

Page 35: Sviluppare app event-driven con RxJava su Android

Sviluppare App event-driven con RxJava su Android - Boris D’Amato

Grazie.

@borisdamato

+BorisDAmato