Komme i gang med ReactiveX på Android

Introduksjon

Utvikling av en kompleks Android-app som har mange nettverkstilkoblinger, brukerinteraksjoner og animasjoner betyr ofte å skrive kode som er full av nestede tilbakeringinger. Slike koden, noen ganger kalt callback helvete, er ikke bare lang og vanskelig å forstå, men også feilaktig. ReactiveX tilbyr en alternativ tilnærming som er både klar og konsis, for å administrere asynkrone oppgaver og hendelser.

RxJava er en JVM-implementering av ReactiveX, utviklet av NetFlix, og er veldig populær blant Java-utviklere. I denne opplæringen lærer du hvordan du bruker RxJava-bindinger for Android, eller RxAndroid for kort, i Android-prosjektene dine.

1. Sette opp RxAndroid

For å bruke RxAndroid i et Android Studio-prosjekt, legg det til som en kompilere avhengighet i appmodulets build.gradle.

java kompilere 'io.reactivex: rxandroid: 0.25.0'

2. Grunnleggende om observatører og observables

Når du arbeider med ReactiveX, bruker du observerbare observatører og observatører. Du kan tenke på en observerbar som et objekt som sender data og en observatør som et objekt som bruker dataene. I RxJava og RxAndroid er observatører forekomster av Observer grensesnitt, og observerbare er forekomster av observer klasse.

De observer klassen har mange statiske metoder, kalt operatører, å lage observer objekter. Følgende kode viser hvordan du bruker bare operatør for å lage en veldig enkel observer som utsender en enkelt string.

java Observerbar myObservable = Observable.just ("Hello"); // Utsender "Hei"

Den observerbare vi nettopp har opprettet, vil kun gi ut data når den har minst en observatør. For å opprette en observatør, oppretter du en klasse som implementerer Observer grensesnitt. De Observer grensesnittet har intuitivt navngitte metoder for å håndtere ulike typer meldinger det kan motta fra det observerbare. Her er en observatør som kan skrive ut string utsendt av det observerbare vi opprettet tidligere:

"Java Observer myObserver = ny Observer() @Overtrid offentlig tomgang på Fullført () // Kalt når det observerbare ikke har mer data å sende ut

@Override public void onError (Throwable e) // Kalt når det observerbare møter en feil @Override public void onNext (String s) // Kalt hver gang det observerbare sender data Log.d ("MY OBSERVER", s) ; ; "

For å tilordne en observatør til en observerbar, bør du bruke abonnere metode, som returnerer a Abonnement gjenstand. Følgende kode gjør myObserver observere myObservable:

java abonnement mySubscription = myObservable.subscribe (myObserver);

Så snart en observatør legges til det observerbare, utsender det sine data. Derfor, hvis du kjører koden nå, vil du se Hallo skrevet ut i Android Studio logcat vindu.

Du har kanskje lagt merke til at vi ikke brukte onCompleted og onError metoder i myObserver. Da disse metodene ofte blir ubrukt, har du også muligheten til å bruke handling1 grensesnitt, som inneholder en enkelt metode som heter anrop.

java Action1 myAction = ny Action1() @Override offentlig ugyldig samtale (String s) Log.d ("Min handling", s); ;

Når du passerer en forekomst av handling1 til abonnere metode, den anrop Metoden er påkalt når det observerbare sender data.

java abonnement mySubscription = myObservable.subscribe (myAction1);

For å frigjøre en observatør fra det observerbare mens det observerbare fortsatt utsender data, kan du ringe Avslutte abonnementet metode på Abonnement gjenstand.

java mySubscription.unsubscribe ();

3. Bruke operatører

Nå som du vet hvordan du lager observatører og observables, la meg vise deg hvordan du bruker ReactiveXs operatører som kan opprette, transformere og utføre andre operasjoner på observerbare data. La oss begynne med å skape en litt mer avansert observer, en som sender ut elementer fra en rekke Integer objekter. For å gjøre det må du bruke fra operatør, som kan generere en observer fra arrays og lister.

"java observerbar myArrayObservable = Observable.from (new Integer [] 1, 2, 3, 4, 5, 6); // Utsender hvert element i gruppen, en om gangen

myArrayObservable.subscribe (ny Action1() @Override offentleg tomgang (Integer i) Log.d ("Min handling", String.valueOf (i)); // Skriver nummeret mottatt); "

Når du kjører denne koden, vil du se hvert av tallene i arrayet som skrives ut en etter en.

Hvis du er kjent med JavaScript, Ruby eller Kotlin, kan du være kjent med høyere rekkefølge funksjoner som kart og filter, som kan brukes når du arbeider med arrays. ReactiveX har operatører som kan utføre lignende operasjoner på observerbare data. Men fordi Java 7 ikke har lambdas og høyereordningsfunksjoner, må vi gjøre det med klasser som simulerer lambdas. For å simulere en lambda som tar ett argument, må du lage en klasse som implementerer func1 grensesnitt.

Slik kan du bruke kart operatør for å firkantet hvert element av myArrayObservable:

java myArrayObservable = myArrayObservable.map (ny Func1() // Input og Output er både Integer @Override public Integer call (Integer integer) retur heltall * heltall; // Plasser nummeret);

Legg merke til at anropet til kart operatør returnerer en ny observer, det endrer ikke originalen observer. Hvis du abonnerer på myArrayObservable nå vil du motta firkanter av tallene.

Operatører kan kjedes. For eksempel bruker den følgende kodeblokken hoppe operatør for å hoppe over de to første tallene, og deretter filter operatør for å ignorere odde tall:

"java myArrayObservable .skip (2) // Hopp de to første elementene .filter (nytt Func1() @Override det offentlige boolske anropet (Integer heltall) // Ignorerer noe element som returnerer falskt retur heltall% 2 == 0; );

// Utsender 4 og 6 "

4. Håndtering av asynkrone jobber

Observatørene og observablene vi opprettet i de foregående delene, jobbet på en enkelt tråd, Android's UI-tråd. I denne delen vil jeg vise deg hvordan du bruker ReactiveX til å administrere flere tråder og hvordan ReactiveX løser problemet med tilbakekallingshelvete.

Anta at du har en metode som heter fetchData som kan brukes til å hente data fra en API. La oss si at det aksepterer en nettadresse som parameter og returnerer innholdet i svaret som en string. Følgende kodestykke viser hvordan det kan brukes.

java String content = fetchData ("http://www.google.com"); // henter innholdet på google.com som en streng

Denne metoden må kjøre på egen tråd, fordi Android tillater ikke nettverksoperasjoner på brukergrensesnittet. Dette betyr at du enten vil opprette en AsyncTask eller opprett en Tråd som bruker a handler.

Med ReactiveX har du imidlertid et tredje alternativ som er litt mer konsistent. Bruker subscribeOn og observeOn operatører, kan du spesifikt spesifisere hvilken tråd som skal kjøre bakgrunnsjobben, og hvilken tråd som skal håndtere brukergrensesnittoppdateringene.

Følgende kode oppretter en egendefinert observer bruker skape operatør. Når du oppretter en observer På denne måten må du implementere Observable.OnSubscribe grensesnitt og kontrollere hva det sender ut ved å ringe onNext, onError, og onCompleted metoder selv.

java Observerbar fetchFromGoogle = Observable.create (ny Observerbar.OnSkriv inn() @Overtrid offentlig tomt-anrop (Abonnent abonnent) prøv String data = fetchData ("http://www.google.com"); subscriber.onNext (data); // Utgitt innholdet i URL abonnenten.onFullført (); // Ingenting mer å sende ut] fange (Unntak e) abonnent.onError (e); // I tilfelle det er nettverksfeil);

Når observer er klar, kan du bruke subscribeOn og observeOn å spesifisere tråder den skal bruke og abonnere på den.

java fetchFromGoogle .subscribeOn (Schedulers.newThread ()) // Opprett en ny tråd .observeOn (AndroidSchedulers.mainThread ()) // Bruk brukergrensesnittet .subscribe (new Action1() @Override offentlig ugyldig samtale (String s) view.setText (view.getText () + "\ n" + s); // Endre en visning);

Du kan fortsatt tenke at den reaktive tilnærmingen ikke er drastisk bedre enn å bruke AsyncTask eller handler klasser. Du har rett, du trenger ikke virkelig ReactiveX hvis du bare må klare en bakgrunnsjobb.

Nå vurderer et scenario som ville resultere i en kompleks kodebase hvis du brukte den konvensjonelle tilnærmingen. La oss si at du må hente data fra to (eller flere) nettsteder parallelt og oppdatere a Utsikt bare når alle forespørsler har fullført. Hvis du følger den konvensjonelle tilnærmingen, må du skrive mye unødvendig kode for å sikre at forespørslene er fullført uten feil.

Vurder et annet scenario der du må starte en bakgrunnsjobb bare etter at en annen bakgrunnsjobb har fullført. Ved hjelp av konvensjonell tilnærming vil dette resultere i nestede tilbakeringinger.

Med ReactiveXs operatører kan begge scenariene håndteres med svært liten kode. For eksempel, hvis du må bruke fetchData for å hente innholdet på to nettsteder, for eksempel Google og Yahoo, ville du opprette to observer objekter, og bruk subscribeOn metode for å få dem til å løpe på forskjellige tråder.

java fetchFromGoogle = fetchFromGoogle.subscribeOn (Schedulers.newThread ()); fetchFromYahoo = fetchFromYahoo.subscribeOn (Schedulers.newThread ());

For å håndtere det første scenariet der begge forespørslene må kjøre parallelt, kan du bruke glidelås operatør og abonnere på observer det kommer tilbake.

java // Hent fra begge samtidig Observable zipped = Observable.zip (henteFromGoogle, henteFromYahoo, ny Func2() @Override public String call (String google, String yahoo) // Gjør noe med resultatene fra begge tråder returnere google + "\ n" + yahoo; );

På samme måte, for å håndtere det andre scenariet, kan du bruke concat operatør for å kjøre trådene etter hverandre.

java Observerbar concatenated = Observable.concat (fetchFromGoogle, fetchFromYahoo); // Utsende resultatene etter hverandre

5. Håndtering av hendelser

RxAndroid har en klasse som heter ViewObservable som gjør det enkelt å håndtere hendelser knyttet til Utsikt objekter. Følgende kodestykke viser deg hvordan du lager en ViewObservable som kan brukes til å håndtere klikkhendelser av a Knapp.

"java Button myButton = (Button) findViewById (R.id.my_button); // Lag en knapp fra et layout

observer klikkObservable = ViewObservable.clicks (myButton); // Opprett en visningOvervålig for knappen "

Du kan nå abonnere på clicksObservable og bruk noen av operatørene du lærte om i de forrige avsnittene. Hvis du for eksempel vil at appen din skal hoppe over de fire første klikkene på knappen og begynne å svare fra femte klikk, kan du bruke følgende implementering:

java klikk. Observerbar .skip (4) // Hopp over de første 4 klikkene. Abonnere (ny Action1() @Overtrid offentlig tomgang (OnClickEvent onClickEvent) Log.d ("Klikk Action", "Clicked!"); // Trykt fra femte klikk og fremover);

Konklusjon

I denne opplæringen lærte du hvordan du bruker ReactiveXs observatører, observables og operatører til å håndtere flere asynkrone operasjoner og hendelser. Som å jobbe med ReactiveX involverer funksjonell, reaktiv programmering, er et programmeringsparadigm de fleste Android-utviklere ikke vant til, ikke vær for vanskelig på deg selv hvis du ikke klarer det riktig første gang. Du bør også vite at ReactiveX-koden vil være mye mer lesbar hvis du bruker et moderne programmeringsspråk, for eksempel Kotlin, som støtter høyere rekkefølgefunksjoner.

Hvis du vil vite mer om reaktive utvidelser, oppfordrer jeg deg til å bla gjennom ressursene som er tilgjengelige på ReactiveX.