Komma igång med ReactiveX på Android

Introduktion

Att utveckla en komplex Android-app som har massor av nätverksanslutningar, användarinteraktioner och animeringar betyder ofta skrivkod som är full av kapslade återuppringningar. Sådan kod, kallas ibland callback helvete, är inte bara lång och svår att förstå, men också felaktig. ReactiveX erbjuder ett alternativt tillvägagångssätt som är både tydligt och koncist, för att hantera asynkrona uppgifter och händelser.

RxJava är en JVM-implementering av ReactiveX, utvecklad av NetFlix, och är mycket populär bland Java-utvecklare. I den här handledningen lär du dig att använda RxJava-bindningar för Android eller RxAndroid för kort, i dina Android-projekt.

1. Ställa in RxAndroid

För att använda RxAndroid i ett Android Studio-projekt, lägg till det som en sammanställa beroende av appmodulens build.gradle.

java compile 'io.reactivex: rxandroid: 0.25.0'

2. Grunderna för observatörer och observabler

När du arbetar med ReactiveX använder du observerbarhet och observatörer i stor utsträckning. Du kan tänka på en observerbar som ett objekt som avger data och en observatör som ett objekt som förbrukar den data. I RxJava och RxAndroid är observatörer instanser av Observatör gränssnitt, och observerbara är instanser av Märkbar klass.

De Märkbar klassen har många statiska metoder, kallas operatörer, att skapa Märkbar objekt. Följande kod visar hur du använder bara operatör för att skapa en mycket enkel Märkbar som avger en singel Sträng.

java observerbar myObservable = Observable.just ("Hello"); // Utsänder "Hej"

Den observerbara vi just skapat kommer endast att avge uppgifterna om den har minst en observatör. För att skapa en observatör skapar du en klass som implementerar Observatör gränssnitt. De Observatör gränssnittet har intuitivt namngivna metoder för att hantera olika typer av meddelanden som den kan ta emot från observerbara. Här är en observatör som kan skriva ut Sträng emitteras av det observerbara vi skapade tidigare:

"Java Observer myObserver = ny Observer() @Override public void onCompleted () // Kallas när det observerbara inte har mer data att avge

@Override public void onError (Throwable e) // Kallas när det observerbara möter ett fel @Override public void onNext (String s) // Kallas varje gång det observerbara skickar data Log.d ("MY OBSERVER" s) ; ; "

För att tilldela en observatör till en observerbar bör du använda prenumerera metod som returnerar a Prenumeration objekt. Följande kod gör myObserver observera myObservable:

Java-prenumeration mySubscription = myObservable.subscribe (myObserver);

Så snart en observatör läggs till observerbar, avger den sin data. Därför kommer du att se om du kör koden nu Hej skrivs ut i Android Studio logcat fönster.

Du kanske har märkt att vi inte använde onCompleted och den onerror metoder i myObserver. Eftersom dessa metoder ofta lämnas oanvända har du också möjlighet att använda Åtgärd 1 gränssnitt, som innehåller en enda metod som heter ring upp.

java Action1 myAction = ny Action1() @Override public void call (String s) Log.d ("My Action", s); ;

När du passerar en instans av Åtgärd 1 till prenumerera metod, den ring upp Metoden åberopas när det observerbara släpper ut data.

Java-prenumeration mySubscription = myObservable.subscribe (myAction1);

Att avlägsna en observatör från dess observerbara medan det observerbara fortfarande sänder data kan du ringa säga upp metod på Prenumeration objekt.

java mySubscription.unsubscribe ();

3. Använda operatörer

Nu när du vet hur man skapar observatörer och observabler, låt mig visa dig hur du använder ReactiveXs operatörer som kan skapa, transformera och utföra andra operationer på observerbara data. Låt oss börja med att skapa en något mer avancerad Märkbar, en som avger objekt från en uppsättning av Heltal objekt. För att göra det måste du använda från operatör, som kan generera en Märkbar från arrays och listor.

"java observerbar myArrayObservable = Observable.from (new Integer [] 1, 2, 3, 4, 5, 6); // Utsänder varje objekt i matrisen, en i taget

myArrayObservable.subscribe (ny Action1() @Override public void call (Integer i) Log.d ("My Action", String.valueOf (i)); // Skriver ut det mottagna numret); "

När du kör den här koden ser du var och en av numren på matrisen som skrivs ut en efter en.

Om du är bekant med JavaScript, Ruby eller Kotlin kanske du känner till högre orderfunktioner som Karta och filtrera, som kan användas vid arbete med arrays. ReactiveX har operatörer som kan utföra liknande operationer på observerbara data. Men eftersom Java 7 inte har lambdas och högre orderfunktioner, måste vi göra det med klasser som simulerar lambdas. För att simulera en lambda som tar ett argument måste du skapa en klass som implementerar FUNC1 gränssnitt.

Så här kan du använda Karta operatör för att ruta varje objekt av myArrayObservable:

java myArrayObservable = myArrayObservable.map (ny Func1() // Input och Output är både Integer @Override public Integer call (Integer heltal) return heltal * heltal; // Ruta nummeret);

Observera att samtalet till Karta operatören returnerar en ny Märkbar, det ändrar inte originalet Märkbar. Om du prenumererar på myArrayObservable nu får du kvadrater av siffrorna.

Operatörer kan kedjas. Till exempel använder följande kodblock hoppa operatör för att hoppa över de två första siffrorna, och sedan filtrera operatör för att ignorera udda nummer:

"java myArrayObservable .skip (2) // Hoppa över de två första objekten .filter (ny Func1() @Override det offentliga boolesiska samtalet (heltals heltal) // Ignorerar något objekt som returnerar false return integer% 2 == 0; );

// Utsänder 4 och 6 "

4. Hantering av asynkrona jobb

Observatörer och observables som vi skapade i de tidigare avsnitten arbetade på en enda tråd, Android-användargränssnittet. I det här avsnittet kommer jag att visa dig hur du använder ReactiveX för att hantera flera trådar och hur ReactiveX löser problemet med callback helvete.

Antag att du har en metod som heter fetchData som kan användas för att hämta data från ett API. Låt oss säga att den accepterar en URL som dess parameter och returnerar innehållet i svaret som en Sträng. Följande kodsedel visar hur det kan användas.

java String content = fetchData ("http://www.google.com"); // hämtar innehållet på google.com som en sträng

Den här metoden måste köras på egen tråd, eftersom Android inte tillåter nätverksoperationer på användargränssnittet. Det betyder att du antingen skapar en AsyncTask eller skapa en Tråd som använder a Hanterare.

Med ReactiveX har du dock ett tredje alternativ som är lite mer koncist. Använda subscribeOn och observeOn operatörer kan du explicit ange vilken tråd som ska köra bakgrundsarbetet och vilken tråd som ska hantera uppdateringarna för användargränssnittet.

Följande kod skapar en anpassad Märkbar använda skapa operatör. När du skapar en Märkbar På detta sätt måste du genomföra Observable.OnSubscribe gränssnitt och kontrollera vad det emitterar genom att ringa onNext, onerror, och onCompleted metoder själv.

java observerbar fetchFromGoogle = Observable.create (nytt Observable.OnSubscribe() @Override public void call (Subscriber abonnent) försök String data = fetchData ("http://www.google.com"); subscriber.onNext (data); // Avsänd innehållet i URL-abonnenten.onKompletterad (); // Inget mer att avge fånga (Undantag e) subscriber.onError (e); // Om det finns nätverksfel);

När Märkbar är klar, du kan använda subscribeOn och observeOn att ange de trådar som ska användas och prenumerera på det.

java fetchFromGoogle .subscribeOn (Schedulers.newThread ()) // Skapa en ny tråd .observeOn (AndroidSchedulers.mainThread ()) // Använd användargränssnittet .subscribe (new Action1() @Override public void call (String s) view.setText (view.getText () + "\ n" + s); // Ändra en vy);

Du kanske fortfarande tänker på att det reaktiva tillvägagångssättet inte är drastiskt bättre än att använda AsyncTask eller Hanterare klasser. Du har rätt, du behöver inte verkligen ReactiveX om du bara behöver hantera ett bakgrundsarbete.

Tänk nu på ett scenario som skulle resultera i en komplex kodbas om du använde den konventionella metoden. Låt oss säga att du måste hämta data från två (eller flera) webbplatser parallellt och uppdatera a Se först när alla förfrågningar har slutförts. Om du följer det konventionella tillvägagångssättet måste du skriva mycket onödigt kod för att se till att förfrågningarna är färdiga utan fel.

Tänk på ett annat scenario där du bara måste starta ett bakgrundsarbete först efter det att ett annat bakgrundsarbete har slutförts. Med hjälp av det konventionella tillvägagångssättet skulle detta resultera i inbäddade återuppringningar.

Med ReactiveX operatörer kan båda scenarier hanteras med mycket liten kod. Till exempel, om du måste använda fetchData att hämta innehållet på två webbplatser, till exempel Google och Yahoo, skulle du skapa två Märkbar objekt och använd subscribeOn metod för att få dem att köra på olika trådar.

java fetchFromGoogle = fetchFromGoogle.subscribeOn (Schedulers.newThread ()); hämtaFromYahoo = hämtaFromYahoo.subscribeOn (Schedulers.newThread ());

För att hantera det första scenariot där båda förfrågningarna måste köras parallellt, kan du använda blixtlås operatör och prenumerera på Märkbar det återvänder.

java // Hämta från båda samtidigt Observable zipped = Observable.zip (hämtaFromGoogle, hämtaFromYahoo, ny Func2() @Override public String call (String google, String yahoo) // Gör något med resultaten från båda tråden returnera google + "\ n" + yahoo; );

På samma sätt, för att hantera det andra scenariot, kan du använda concat operatör för att köra trådarna en efter en.

java observerbar concatenated = Observable.concat (fetchFromGoogle, fetchFromYahoo); // Utsänd resultaten efter varandra

5. Hantering av händelser

RxAndroid har en klass som heter ViewObservable som gör det enkelt att hantera händelser som hör samman med Se objekt. I följande kodfragment visas hur du skapar en ViewObservable som kan användas för att hantera klickhändelserna i a Knapp.

"java Button myButton = (Button) findViewById (R.id.my_button); // Skapa en knapp från en layout

Märkbar klickObservable = ViewObservable.clicks (myButton); // Skapa en ViewObservable för knappen "

Du kan nu prenumerera på clicksObservable och använd någon av de operatörer du lärde dig om i de föregående avsnitten. Om du till exempel vill att din app ska hoppa över de första fyra klickarna på knappen och börja svara från det femte klicket, kan du använda följande implementering:

java clicksObservable .skip (4) // Hoppa över de första 4 klick .subscribe (new Action1() @Override public void call (OnClickEvent onClickEvent) Log.d ("Click Action", "Clicked!"); // Tryckt från det femte klicket framåt);

Slutsats

I denna handledning lärde du dig att använda ReactiveX observatörer, observables och operatörer för att hantera flera asynkrona operationer och händelser. Att arbeta med ReactiveX innebär att funktionell, reaktiv programmering, ett programmeringsparadigm, som de flesta Android-utvecklare inte brukar vara, inte vara för hårt om du inte förstår det rätt första gången. Du bör också veta att ReactiveX-koden blir mycket mer läsbar om du använder ett modernt programmeringsspråk, till exempel Kotlin, som stöder högre orderfunktioner.

Om du vill veta mer om reaktiva tillägg, uppmanar jag dig att bläddra bland de resurser som finns tillgängliga på ReactiveX.