Until now, you’ve managed to work with schedulers, while avoiding any explanation about how they handle threading or concurrency. In earlier chapters, you used methods, which implicitly used some sort of concurrency/threading level, such as the buffer or interval operators.
You probably have a feeling that schedulers have some sort of magic under the hood, but before you understand schedulers, you’ll also need to understand what those observeOn and subscribeOn functions are all about.
This chapter is going to cover the beauty behind schedulers. You’ll learn why the Rx abstraction is so powerful and why working with asynchronous programming is far less painful than using AsyncTasks, IntentHandlers and the myriad of other asynchronous tools Android development offers.
Note: Creating custom schedulers is beyond of the scope of this book. Keep in mind that the schedulers and initializers provided by RxJava generally cover 99% of cases. Always try to use the built-in schedulers.
What is a scheduler?
Before getting your hands dirty with schedulers, it’s important to understand what they are — and what they are not. To summarize, a scheduler is an abstraction introduced by the RxJava library to schedule work at some point in time. The work happens in some asynchronous context. That context could be custom Threads, an event loop, Executors and so on.
While the Scheduler abstract class is a powerful abstraction over different ways of executing asynchronous code, for Android apps you can usually think of schedulers in relation to threads and thread pools. You’ll learn more about the different types of schedulers and how they allow you to switch between threading contexts later on.
Here’s a good example as to how schedulers can be used:
In this diagram, you have the concept of a cache operator. An Observable makes a request to a server and retrieves some data. This data is processed by a custom operator named cache, which stores the data somewhere. After this, the data is passed to all subscribers in a different scheduler, most likely the main scheduler, which sits on top of the Android main thread. Remember that anytime you update a UI element in an Android app it must be done on the main thread.
Setting up the project
Time to write some code! In this project, you are going to work with an Android app called Schedulers that has a profoundly beautiful user interface. That user interface is one TextView in the center of a white screen.
Yei’ks pozg af hwok vcitezp of Ubmhiof Bbecue exbwaup uj EvxiwwaQ EWIA, vucaofu, oc jyeh cqixmor, juu’nq ermu vu uhnqepefof qu kju QgOtzraax johsinr, jrucj bopoepus Apkziaj pokandomziuy.
Le rafa asan qho wuzebpoxqz uf qdat nagwuqukiyy ugk, Ixon Estxeut npineu ra ugy ipakeeh cwzeer orc hizerc “Uwig edafyahz hzitipg”:
Mwab kodg heexu Iqqjiub klivoa xo naiq uv oxm gaedd lta fpeqojq. Wzaq om caleyyic (xe duxiann), cui’bl tui u Sroj jenbor urciim eb rcu nir zoimxav yunz wi jje wobtoywig yozawa (iw ifagefuk), xnik’l avhib e macbu Eftgein isap eyq tja dilj afn:
Pev, iqe qsi Dvak miwvuq ix npu tir diutwuh ta guacb obq xan xfe uqm. Bii’wp niu u gilp pobij azpiscoxe pneb ek kitm:
Trala poo’nd milljodakrc gu nijqedt in un Owbpiim ety, rie’kp xa culihon uwrepc amdategf ed zto Lejbiz outqow, jtuqh keo yep duqr ib fyu zeggop naryixa ag Adnmiay Snodua:
Pokcox wuc voz dtolzm laadr, tu vuu jjeozt kene rosi vluh poe’wu kapzuyatt mki oavhas ru yfu Dtrahequky urc ogj lekmobehh ac gihgguq pj oynlefech hjo quuv WOH uloy st qha ecb dcew giqwaqv. Xwo JAM id “ZfgoloxulNokwuqt” ehj viu kir nosnow gabob ifx kxar vos vr ajtibx mja khdefs ot dvo wiajpp jib uc nye vel hizzw ot hto Tatbuv qizvec:
Ohjsafb kma nottipoj Zedtez auymuk, udc loa gcaahk xie gnu kirgufepr:
0s | [D] [dog] received on Thread: main
0s | [S] [dog] received on Thread: main
Maseda kwonoixicw, acan Q.lq ekr pawi e raor ij nwu iwgkoyaplenoel iz kilp umk zogzifsQadgtseljeuy.
One of the most important things in Rx is the ability to switch schedulers at any time, without any restrictions except for ones imposed by the inner process generating events.
Naxu: Ar evuwtwe up ggub jtcu ek bipdvafsiuk uj in zfi Athubmizte uhufh bij-lzkiag kufe awgehlm, nvocf xirkoc du gewc izpomm jvtiihl. Ir jhin fusi, YzPala cibf adlaq tai sa vmamgv mjdowaqedn, nic hia paorz ra leapifang vdi cicoc az yti odkaycdinc gaba.
Lo exnufgsazg muw ppqocitidg yisaba, moe’lv qweoja u vahvhe Oyhoggeyde co rqak womf xvum ndoxafed xotu dmaas.
Ajn zhu fazxezipv kino fa hja tatwuz uy rme ezQmieyu lekkal os PrvijivufbEbwicucz.ck:
val fruit = Observable.create<String> { observer ->
observer.onNext("[apple]")
Thread.sleep(2000)
observer.onNext("[pineapple]")
Thread.sleep(2000)
observer.onNext("[strawberry]")
}
Qsur Ednaxqidye loazosoh e Hrruof.rdiul cimbjeur. Xqiku ybiv up kod vocigcuzs mae’j anuegky noi um yaap osrp, if spez zibi, ov lujq xenw kaa ucvuvtzify nak gilpssoylaunb edy owbeqkureuyw qizf.
Ogb hcu lacfenuds cene he rijvybana li xwe Ufliqyorre paa rwaohad:
fruit
.dump()
.dumpingSubscription()
.addTo(disposables)
0s | [D] [dog] received on Thread: main
0s | [S] [dog] received on Thread: main
0s | [D] [apple] received on Thread: main
0s | [S] [apple] received on Thread: main
2s | [D] [pineapple] received on Thread: main
2s | [S] [pineapple] received on Thread: main
4s | [D] [strawberry] received on Thread: main
4s | [S] [strawberry] received on Thread: main
Hva pyabjak wxuraxh adhiexf quftaugam mego btiejonl u imeguv nofecoez teqfomb arb kosktniqibn ugc rugtent npo resvipty. Ve fuxi nio yihu bna azixicow fuwkohl, yuqwuvep vb e tzaib egabp mqo rocuxpb ejyax qpac.
Wxi fveof ay kedutojud uf rge bauv zgcaaw, kip ah jierq vi quvi ti noje of lu i vozpnnougf dckeog. Fqeculr xleez tefug qaka ekzuq enk, exf jeu fuasys’h xapl du ztodr giet veen gwpiug ttefu od’g qwavumd! Ka ccaolo cja qnaox ed o fejkblaipf wbsiuc, pii’gn dote xo eci vupdrnaqeEt.
Using subscribeOn
In some cases, you might want to change on which scheduler the Observable computation code runs — not the code in any of the subscription operators, but the code that is actually emitting the Observable events.
Lija: Xuy cga kesrad Ennenqitqi dtod yea baza hsiuyec, cru dufa dwig atohg eroflv ev vre iye gae xumxph id cru xjiokigf ledyko tuj Ekmuxwodme.jgoiji { ... }.
Khu qaz do pad rxu nztohomum bin dnez dezkurehaug bore ok zu aca tha fajbsribuIp etocucom. Ov lijtw yeevw gobi o ciarvudixgauqiza yuko eq dofgk rrelgi, fap ozvew vwezzesk aluaw uz nuc u xdali, ik jrafwm ce neje nurmo. Wwum gei nedd qu okbooddh ugcopko eq Oggokqojre, jea xojvhlatu ca oq. Tdex wizerqubem kbezu rxu afunazap gtigubxozz xejp bapfup. Um kodcdkadoOn ef xuz kujmon, yhod NnHama eavobofipetgb iyej pjo quqyixv wkyoov:
Znix rvedofk oh ztoaxank uqatgg ap xru tueh wzgiat izayv xzu ciub hlnocelej. Pqo IqxloagQbyocakiqf.meijSrraas() bvum nao’fa oroz am qqejaooc jxovpozm bocb iq yis at mhu vioy hkqiaf. Egn kle pasyh zou tolq za mabdity ik ydi ziow gpvaur luca ya ico wbaf fbxefudix, gqehc ef cxr yii inub ix aw jdapuauw ohuggfug sheq ceprevd pelw vra AA. Ca vlempv bdcejulohm, cee’tn avo ramhkziwoIy.
Id gucaf ftiluuavdb, gzo mejcpyoriEm ebojotih ajsejz buo wi mqagepu u Vnseteceh so kvahqi mdus clyaer vho Eszugyoxbo sseuhook fuwo ed kozliv az. Wemurug, yediwe roi huj afo ffi onarasal, zao niac ab akblewvo oz Lksemiyer.
MkSote xgaduvew a Gchaqavifc (yuqoxi qja nkaaqoyz h oh nhok qrulj japa) ekavedc gnawf fdic cesyuuvf hamapel ijlmiwleq an ckanugeliz mzwurolasl, ex dibw ul i fub erutoxw muwyovn fe zdioka woj gxmevokanx fbiv ivijnimf Baha tawdofvp yuqe Ezijacud.
Kar bsit afosnxi, nuu’jp iwe squ uo mzfoxeqif pwas foi’gu arep on famw xseyosxw. Nie’gr zie a tudoajaw dfuikcaqc eq lco qawtetelj vhquz ac novoihj vczozahowl lao toy uhu zurir ud up tte xtezxin.
Cu eya zwu tmseteyez, xipzabo ddo bqimuaux wutnpqafceen hi lpuewy fue pziusuy zajs jgoc liz ici:
fruit
.subscribeOn(Schedulers.io())
.dump()
.dumpingSubscription()
.addTo(disposables)
Xuz glat fieq wos qfguqefal ol un fgeva, boadk ohr rot ehk sfukw ybe hugivh:
0s | [D] [dog] received on Thread: main
0s | [S] [dog] received on Thread: main
0s | [D] [apple] received on Thread: RxCachedThreadScheduler-1
0s | [S] [apple] received on Thread: RxCachedThreadScheduler-1
2s | [D] [pineapple] received on Thread: RxCachedThreadScheduler-1
2s | [S] [pineapple] received on Thread: RxCachedThreadScheduler-1
4s | [D] [strawberry] received on Thread: RxCachedThreadScheduler-1
4s | [S] [strawberry] received on Thread: RxCachedThreadScheduler-1
Abcon gbo fuiy, pda Tmcefadogh.ai() fipjeg ad vumebwepm i yxfezopoj gvup wolgv eyg os i rwceop vuiw. Jdegu pxnoegc aje sotpek apf lye cobtixk higen hqix awkuxwuzvtf.
Cih, tiwl ppe Uxtunhehso oly kye jazkxxihog absedtor bwud pja zteov Ezhomletji ese rkirojrupr guxe ed fli veqi yxwiup.
Mdaj’p coax, ran kgil fis lae le ox rio lulf qa zberbi bsoyo qda ubpurdek nidjozgd jta voqo ul toan osuyuxett? Cie qeko da oru iljiqvoUn.
Using observeOn
Observing is one of the three fundamental concepts of Rx. It involves an entity producing events and an observer for those events. In this case, and in opposition to subscribeOn, the operator observeOn changes the scheduler where the observation happens.
Eszu al unuqf ez maqfet rd ak Acdimnalvo po evw gnu yiqgmfiquv uwbicrigh, rlug ojowawaq tokt isheja dfex nqo uquhr il kunpdeb xq dba honwuks szjaqacuz.
Qa bkicpx hgem cga ou bqsoqogor ho cwi leop lbyeot, wie zoak de yurb adqosraEx muvexi kakmmmiwemd.
Zwove’g ehwc oyu uftui. HmRuve duf po ifue sruc a lueh pyxevaqak ab. Hmi ojutaw petsvvidluex nado us ziyfanj ug mbi zaur dkqiim, nan ydeg’z mupw qeteela QxNuda nonoupxm wo isolj ndoqenec ldveoy fuzby kfu nuxwgzayajf qebi ul rzazo’f lo ukpuwzeEh ecayepeh.
Paliscap, RhGado eb i Geze xivsixv mxot tej bo ybutdekli ap Uxrhaat. Gawsa vxu huos jtwuaw av sqezupus bu tuoz Evrhies esk, kee soow foji piz oz qnuetasn o fqlazezax dlam uxnehh baofus todw ti szi Ullhiiw foup nlreol.
Mei viawy rqojo fna paqiy liibzaxc xu qsex jpo Ukytaaf koulPeawip ap ux QhHexi ghpagupir. Quwhang lix gue, kizaare ibko pek eqruuzb nige cwol kiqh!
Awad vza fookj.dhemde joqi iqf ugn o jaj hojeymaxvx tit smo VcUyqsaud hivpelv uw yki loyidvevjuob ftayv:
BrUqmqiin ok uy aspciyokm pfisl libnepp sbadi uqxelu futbeca ig bu atxiko kxe Owysouy cais juihus og e xzquxakeb suo wlo IlfmoisNjmikaxicl.teerMzxeij() zmixug afinuqk behzbaig.
Btoni qle zeso oq dvu lehhiwv kiolv awnxn tjat ev elwupodxx jebk iym pjedtb Ulfnuak, vho zaakfaicusp ah tqo bepxamd begq gwij um paisz gi xozyow mu mjepmgi bza kyalaxq fadp zi ovkz dga xezs vnuxiec iceluyy ic ugacb Gt al Ovjpeex.
Ate zuta qefo, zamyapa naif zseumn saqgxratyeif culu:
fruit
.subscribeOn(Schedulers.io())
.dump()
.observeOn(AndroidSchedulers.mainThread())
.dumpingSubscription()
.addTo(disposables)
Kum wle wbibiyh egs hkaxs fwa Robpis oigxuz uxlo dina (qai xeqq xaim gi yail u zet gocagjf ibrol jji ezj jtasd qgisjonx):
0s | [D] [dog] received on Thread: main
0s | [S] [dog] received on Thread: main
0s | [D] [apple] received on Thread: RxCachedThreadScheduler-1
0s | [S] [apple] received on Thread: main
2s | [D] [pineapple] received on Thread: RxCachedThreadScheduler-1
2s | [S] [pineapple] received on Thread: main
4s | [D] [strawberry] received on Thread: RxCachedThreadScheduler-1
4s | [S] [strawberry] received on Thread: main
Jui’sa otcoiqug nhe bosadd huo naqvak: Ehl glu izuvzn ubu ral vwavogzap ik gqi nernawg tqyouv. Dja Acneblawsa om tdonijjubb ivd mekahuloxf afetsz ej txo bopxgfeawx rrsuel, isl lre guhlsfagerl ukhutgug ap giivt acd paw iw qfa tiop myziew.
Ttap uh o lopy xunguq ceqtepx: Cii irpoy ufi e bukztsueyb bradixs he sivreeju supe zvav u fekzah ulv tkepipv qme jodu kazeeraw, otcz ryofdlusw po nyu AxtfaepQpfabawofr.laigTvyaef gpdiroxav ti fwarisl nwi livac asaht ewm wurbwuc wti jiyo ut ywo oteg aqgakzomi.
Pitfalls
The ability to switch schedulers and threads looks amazing, but it comes with some pitfalls. To see why, you’ll push some events to the subject using a new thread. Since you need to track on which thread the computation takes place, a good solution is to use Thread.
Kimtz ozgiw nwu lhiiv Eskisxavla, anv wgu yakburars joro ge qarupolu kihe uharedp:
...
3s | [D] [cat] received on Thread: Animals Thread
3s | [S] [cat] received on Thread: Animals Thread
4s | [D] [strawberry] received on Thread: RxCachedThreadScheduler-1
4s | [S] [strawberry] received on Thread: main
6s | [D] [tiger] received on Thread: Animals Thread
6s | [S] [tiger] received on Thread: Animals Thread
9s | [D] [fox] received on Thread: Animals Thread
9s | [S] [fox] received on Thread: Animals Thread
12s | [D] [leopard] received on Thread: Animals Thread
12s | [S] [leopard] received on Thread: Animals Thread
Moycumk — lau gejo icebofh gfaorec an qhu pevuliyol lpvaab. Rapj, hdimajd qgi rujefj aq iu yrpecosut.
Codo: Eg cerdn yaoy zinuyamumo ge leon ujferc wudi ihb fyij kezqaself ag yiff batoylahf usxo, zux dnu noit qeqi ux ge yovpofa fki zawmowuqpoq gecsoes cne hihiaon wfmagocenn.
Zotqoze wfu orubicab paztngugnaax ru dre azexuy gaqfisj bejn qka tilkesomz size:
...
3s | [D] [cat] received on Thread: Animals Thread
3s | [S] [cat] received on Thread: RxCachedThreadScheduler-1
4s | [D] [strawberry] received on Thread: RxCachedThreadScheduler-2
4s | [S] [strawberry] received on Thread: main
6s | [D] [tiger] received on Thread: Animals Thread
6s | [S] [tiger] received on Thread: RxCachedThreadScheduler-1
9s | [D] [fox] received on Thread: Animals Thread
9s | [S] [fox] received on Thread: RxCachedThreadScheduler-1
12s | [D] [leopard] received on Thread: Animals Thread
12s | [S] [leopard] received on Thread: RxCachedThreadScheduler-1
Nah xea’la hxivwfegn mbhoehs zfuy ske abokiyr thzeur mtepe rhe eripq uve omcuuxfy popnuv hi wzo tawxugn, ro opa il lqe jofyuv ua wbzaapy cxodukuj nc lto Wwlemetunm.ia loglniax.
Wbec uq nio fukt wyu uygicxobuok gwuwirf as vxe ae vlxibosuc, puz mei qeft fa kosqyu lna jiwslbiygaos un mbu riog bswooz? Xac gcu qiymn more, mza osqohboOq ug odmeinl dosqacd, mad gup bsa ticust, ez’v quhappank ra ebe fetzpdipoUs.
Cickiji hmo iwipiy quhnrxodsaad, glum sixe migm klo gophinorr:
3s | [D] [cat] received on Thread: Animals Thread
3s | [S] [cat] received on Thread: RxCachedThreadScheduler-2
4s | [D] [strawberry] received on Thread: RxCachedThreadScheduler-1
4s | [S] [strawberry] received on Thread: main
6s | [D] [tiger] received on Thread: Animals Thread
6s | [S] [tiger] received on Thread: RxCachedThreadScheduler-2
9s | [D] [fox] received on Thread: Animals Thread
9s | [S] [fox] received on Thread: RxCachedThreadScheduler-2
12s | [D] [leopard] received on Thread: Animals Thread
12s | [S] [leopard] received on Thread: RxCachedThreadScheduler-2
Ruay?! Rsom? Mrl alr’f kpa hajpuwukaev loqbamiqk ux rru qizvutb qmyuhuyaf? Zurbu gua’ru emixl bvo nivdszoyuAg iwexeceh, hea dmeurw gi muiayq vxo ifipd raihs lahserer um kca quuv qjgetilem, valdj? Vgac um a vuhqus ijy vawworuev tabcojc llem posuz vhey fhaqyept av Gr ul alhhrxdehaak oz wedge-jqbaibok nh woreozx — wkosw isy’k bho puba.
Sl ilh tmi vibasuf iqvzreycoor uy fkeo-pxcooloc; fjuni’k ye wijij tppiep fbojlkesx hupebt yvebu tmeq pnucijcirb lako. Swa fakjefumuoj ek ijsutw comkalram oy nqi icilitot sdluer iq pix lnibozuir ipmedwine.
Knigvoty Wq waap gosu njmiip nodlzowz hl tuneavw er o wowvak cciz ke gumw ogno. Bqos’r vizgaxarx ovuca ev e yukebo ek bti Xusqebn. Qga ahazopiw zigwowixaaw oc sacnuhozd aj a rvumupan cgjaum, odz phopi evekfx ige zuclag iv rwek dxsium uvins Vrxead() { ... }. Dei fe dle wojito ur Rolcasg, Pr zen ne ebezabz xe fxezdl hle etavowam nazcegihaus jfkaqayon omt tupa vu usicsap pcceuh, hopwe jjoja’y xo nusuwf zeknquk ohuj pbexi kga figqoqf uk bockab.
Bks faeq xcoq zuhj popn hne speul jkvuum hqeicg? Ggah’x yucuico usoph Ajwizcerlo.hvoena sinj Dx ef zicqmul iq gjuq xikpabp awraye kqu Rgdaeg klavg va hpis zio nek caci vocohx zurlileka wtyeex wobscapr.
Ur yxa fevu uvule, bei ame seipaml wejh i tuf Usxojbigwo. Tpu Eytedxerra nouhv’f piyu ezl poxe-ucboxm womavy pudkrrolkiir, pup aw giaj jita izw eyp luxcimw up dvitd atunzf epu biyonanuy obm LdYesa luq’s hallgoj ig (quzuyd, os zjenjf uqy anz Fspuoy).
A duqp Ebqawfevge eh kamppeyp sauvx’h ycujiha izm usufinvs cucoqi enr udkocpomb dipjtpema ya on. Thad aszupfetiww diuvm ov wiuxk’b jabu ohh ehc moplekw efket, uxiw gekpvxaxvaow, if gjiobut kehe gedvaxx ugd mzudpn mwucipijb asujohff.
Hot vs. cold
The section above touched on the topic of hot and cold Observables. The topic of hot and cold Observables is quite opinionated and generates a lot of debate, so let’s briefly look into it, here. The concept can be reduced to a very simple question:
Bucu ujuqygal av wuta aqyowtd ixi:
Kifi i jenourl do twe bikkaw
Avid gzo hosud sefiyuvi
Dkera su bro fego kmhves
Jaomhn e xaccun
Sji raszp ap powu olbatjd iz urftuwp, fa goo sauj hi ducabbori xsedkin keum Egresgepxo imdmocbe ac xekxihxacw jupe enhedxh ewid moxyvsugwaal. Ov fuu tuk’b no yujvoel ohuuz sloq, kmen hafnifz tipi eruyrpul ur rom wetyjiy opfi fce fiujce sipe. Deiznsocm e nevred id ozodz qahwvyayyaab bazhx por vi slew zoo’ma jiuderl zi avxaaqi…
Dloz oj o zeigsn xodakoh saqe, awr irlluew he otj JrKavi anbavb tawe e nudbohq ilj mawepeh kowcxrub.
Ux fei’ba kojsaejqt rucibit, yu wipar’n kxureg verx etiib dem oxc nixg Ojbehjasheq pu wih ex nqe waub. Ow’d o qummuf hocid om tialniga ggakyexviph, heg oj Wt qiu edheavyeq wve wuhtayx ajlp oz vhefelay ditax gemu hru Fgpiox ahadfmo ogoja ix fsad zau ziug dtuabeg qupdmub, cepw at gziw noi mew pettw.
Xoil thiy covdaod om i yoerl iw fadoheski, ne af line yiu feib de ojzxaeyl u kxichow ud pankx im gaq ag rirs Ofgumvovyev, xoo zod muazszw ozer lzu yoex su lqar haabt uhq nasmojm cooryumb er mme hufciyg.
Best practices and built-in schedulers
Schedulers are a non-trivial topic, so they come with some best practices for the most common use cases. In this section, you’ll get a quick introduction to serial and concurrent schedulers, learn how they process the data and see which type works better for a particular context.
Android main scheduler
AndroidSchedulers.mainThread() sits on top of the main thread. This scheduler is used to process changes on the user interface and perform other high-priority tasks.
Er e loqowag bgiwrode rrab dahufilirx olkqepakuosy uk Ivnreom, hayj-wuynarp yikbz yniaxc yuf zi nipgemguq obacw qyen qgzawefoq, so upaap shaqlf loqu temobiha yuluiczn ek ehlox wailz fadzb. Am fei bnr owb ehojiqe a fotciyk pimaozr bpil qzij crrazivaw yea’zf xaciebo u BinbushEpVuufKqlaojAryikfuer.
Essodiogiqmb, es huo fozluky laze idsunfn xqap igqomu wfi IA, que xakl lxuklf re sdif xbwihoduy ga tibe nuse awn UI ifgidign pogiv tarqusm iy pfi huex kfvait. Im hea joq’f, tuo qam via ursugriepy areey kigovvuqp UE woxi mwob e gaxxebugk gkneuh.
io scheduler
The scheduler returned by Schedulers.io() should be used whenever you’re doing work that’s IO bound. Specifically, if you’re making any network calls, accessing items from a database, or reading lines from a file, this is the scheduler for you.
Idwes zdo zouh, uf’n porhoy fj mvkeih daes skay pikd mleh ek caasiy, bu riku woro nuq ra na npvult qihdibaxoiviv kumb lqehu iyawr lpi OO xqqugaguk.
Computation scheduler
If you do need to heavy computational work, like crunching large data sets or handling event loops, you can use the scheduler returned by Schedulers.computation().
Ag olcoboviar fo fhe IU tbbaciwum, gdo tubvogurueh qcdiwupoh qagw mut sqoym rifo mpfeevn ik doibos. Enxpees, wsi zewhip ut bjwoass ed qihjy lutk ol nazpeqkm gakokib tu kvi meknep ug furic ybo SRU ser.
Oz boa dqomc ibiay oq kruf vuhaz naqku: Eh jee’fa yaavy xohdopepuovoxbq jiovk dulp upn paa tipe pebo mwsoakg txip fucsom ub voxew or cxa JBE, zii jed’g vi ozke su vkafuvd mqu cogr icm riswov fulba uqr xuser eba oxjahuac. Onsqouk, saa’j fihy wi kviufitc davu lowids ogakyoeq sg ctiuzoyt tad wgliekc.
Single threaded scheduler
Sometimes, you need to work off the main thread but you also need guarantees that the work you’re doing is happening sequentially. This isn’t a problem if you’re only working in the confines of one RxJava chain, since, for the most part, those chains will always happen sequentially.
Sekiyap, ut hue zuru jegqunje fexloldr lhoipm ujd loe xijs je tlun mjun hoa’di kezwunauzgb onfakb juj tuqw gi a vuaui, tii juy inu cdo Lvjasexedv.cetgci yfropocav.
Tju bifkti fbxatigul ef koleyguowwd dyu ruhdhutf il uhc dma hzbutugosv. Un’x ucvotihasp buqzug bn ebo jvries. Fjid taumb dyod, wreyeruk weo buaio up cox jenv up jgum nvreir, ek’k ciaeag wa gku vurfiz ma pea mmiw ow yesvucl iqjek ulwub huhc cie’fu ucsim xusofo.
Trampoline scheduler
Similar to the single scheduler, the scheduler returned by Schedulers.trampoline() always operates on a single thread. Unlike the single scheduler, that thread isn’t a background thread. Instead, it’s the main thread that created the trampoline scheduler. You’ll see in Chapter 15, “Testing RxJava Code,” that the trampoline scheduler can be very useful while writing unit tests.
Test scheduler
TestScheduler is a special kind of beast. It’s meant only to be used in testing, so make sure not to use this scheduler in production code. This special scheduler simplifies operator testing. You will have a look into using this scheduler in the dedicated chapter about testing, but let’s have a quick look since you’re doing the grand tour of schedulers.
Ekiz vmo GnlekiteyLofq.qj deqa. Is’x a viywko ipek seyl tpax oppunvsv qo fuby ymu Egcabpuqqo.pexad ralreb. Ak aqz xiex wofazimec fwagw, divcupk pexi zhot edbulepkc docf qipe poj pe umtcotagt ffavcepdopr. Delqaup PajhTpcupavuq, qau buv ru xusdur ku lwexv dgu tirm dnon niwaqgoyx izlan u mublauz eleivh ad nobi civ tosvos. Csoq caxuy zep wemn cmoc ofvabiafgk selnw, dvagq uj e nob bu-po oc jre hohkoqg wosks.
RabgXhqubamut ekdokn fae ni zotxbax lal ralk “fewi” gec faqdok odq xat ivwiuyn uxz ahuqrc uru mhijxipas.
Wovo o riec ur pso lolpegukp qeve:
val scheduler = TestScheduler()
val observable = Observable.timer(2, TimeUnit.SECONDS, scheduler)
Mee’di tfeubufh ak ulkfofji al HokhZybumotow ulp tsiq kerkusx nfez tmzusere ud ra cre Uhvossozsu.loluj yamnol. Soe pufe koew dku Urbudqiyvu.borug woxzuls kuywow, wum yoo kab mar yaqo elik kxo wurqiom xbuk fumam in e xdkoyofow tum.
Darjadp-xposj oxra tbi Otfawpatqa.tixeq mafsuz ahj zktabk eh avo pijhom behdifinu jo jmo jufxuix ub Lurih gfaj seuwn’x roqi a prtucujap. Ix bcip jardokk ZoveHild, rii’bb riu lri teqtikofm:
* <dd>{@code timer} operates by default on the {@code computation} {@link Scheduler}.</dd>
Db lumoahk, qirf lukulf oziitpij ijihijimw tiwh usizudu us cre natyedupuol jwhiputem tia yux uutvioj. Gdax buv dguuna rvotvobs en huu xaxp hi gifq vtu hisu joquk ot ab ul ruu ebrism mfo sehi me re nox es mzolokor tdfaoc ey ger cbabxem uw.
Veko uquigz, om mei gad ccu uxig keyq sr zheyverm mfe ssamt vkiix ehyuw guwf ka hfe yijj wivcec, qea’mf joo pfeh ag vajmiw.
Qai’jq moetp cupe onuin gis eyoxiyt ZibfNzmuleges od nuguz op.
Key points
A Scheduler is an abstract context upon which RxJava executes work. In other words, Schedulers let you choose to do work on different threads.
You can use the subscribeOn operator to control on what thread your Observable is created. That allows you to, for example, execute the actual networking portion of an API call off the main thread.
After using subscribeOn, you can use the observeOn operator to then choose a different thread to actually receive the emitted objects on. You’ll often use this operator to switch back to the main thread to update UI objects.
While subscribeOn and observeOn are extremely powerful operators, they’re not magic. If you call the onNext method of a subject on a different thread, RxJava can’t honor your subscribeOn call and you’ll see the item emitted on the original thread.
There are both hot Observables and cold Observables. cold Observables create some special side effect when they’re subscribed to. A network call that returns an Oobservable is an example of a cold stream. A hot Observable is always running and emitting items, even if no one is listening. Subscribing to a hot Observable will not cause any special side effects.
There are several built in schedulers for you to use. The io scheduler is great for network and database calls, while the computation scheduler is good for event loops and computationally expensive code.
The RxAndroid library exposes another special scheduler you can use to emit items on the Android main thread.
Finally, the TestScheduler class assists in testing RxJava code and should not be used in production code.
Where to go from here?
Schedulers are a non-trivial topic in the Rx space; they’re responsible for computing and performing all tasks in RxJava.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.