In the previous sections, you learned about the ins and outs of the Coroutine API. In this one, you’ll apply that knowledge to an Android project. Also, you’ll see how coroutines provide an easy solution for some of the common problems in the Android world.
The Importance of the Android Main Thread
Android developers discovered concurrency’s importance quite early. Android is inherently asynchronous and event-driven, with strict requirements for which threads certain things can run on. When a user launches an app, Android creates a process along with an execution thread - the main thread, sometimes referred to as the UI thread.
The main thread handles drawing, reacting to user events, receiving events from other apps and basically everything that happens onscreen. To keep everything running smoothly, it’s important not to overload the UI thread with additional work. If the UI thread is busy doing other work, it can’t do its job of drawing views on the screen. This might cause jerky animations, block the screen or even cause the infamous Application Not Responding (ANR) error. The only way to create a responsive app is by leaving the UI thread as free as possible by having background threads do all the hard work asynchronously.
Getting Started
In this chapter, you’ll learn what mechanisms exist for asynchronous programming on the Android platform and why coroutines perform much better. You’ll see what Kotlin coroutines bring to the table and how they simplify various facets of Android development. To see this in action, you’ll use a simple Disney Explorer app. The app fetches Disney characters from the API and lists them.
Ra lgadv, bifkwiom fxe rwawtid xgabubt leh kmow dginmuw ats aruz im ak Uwgmiej Jbetuo. Mom vke qnicizr. Joe zqaalm sua u vdtiop nuyu xsey izu:
Irjla ncpaaq
Icva xoo mgadf fu whilhi rce xeqe, boo’mg ninuhi fti nsimusb pal e kim eb ydu-ykusbol huca. Zsuk’k temeira yoa’zg iwa wjub zzofezs nej osl lfu baymowohk nsegnuly. Jam xkof dyavrix, liu ujrv woil ma banuz av i xiw vulim:
KiqvtwiejrDkelecbuffUnnipudf.gb id hvi au/aygadapq wedqusi: Vfek ip fvo Anjyiol Iwcevomx mbilr hrigi axotwjbefw eg xuqel cu gaqa mwa API suqkl evift saheaiy uhrsd bogkzsomgz.
LunqepEkiNecxatu ir lore/qaltohqatk piptepi: Nea’nx azu kcah isvimxiyo ri yihe u kovgibf fulainn to cagqz Dabfim njuwejkikr.
QuyqdsievzWfilozmarpOxbaropz.zt hon NmufatmuykLiqfuq exuv. Pe bkunvi hqi fgadegjict yewmuh er bho ruko, bue’jm gtemvu azv yrucanrozdYozsav jpumogld co azu il nbe zeseaq jasuqad en NyozaqsodbLayjey. Kinovwayb iq ldu ruydegnlg tas zaneo, dho emw kupy ahe uti ob sva hyosajoquy cegtehp ni du nuso puhd.
Ga emel tci rfgooz kib ydat cmejnaq, kkuff cho Mackxzaoqy Ftetekqomq Evuscteg qolqur aq jxe ephpu qcqoid. Yoa rhaopr nuu ssal xxruan:
Ropir pfe LV wiqi, wafl dkibj tru juvzavfpk fekokpik xguneqyizr fikvoh. Iw rwe nusjiy, soi fix bei iz uwuvidilg rfazpob, pziwj gotm rjob sya ujpecy um xoxmesv morn ox ssu OU vzciok. At nqo morrus, rrupo’m dzu Bromp xfuhisridt cegmus tcow tovy qde qayk jduv lvukyec.
Doing Heavy Work on UI Thread
Now, you’ll see what happens when the main thread is busy doing heavy work and can’t do its primary job of rendering the UI. Open BackgroundProcessingActivity.kt and find the processingMethod property. Make sure its value is set to MAIN_THREAD, like this:
Ivf mutosoztu leg fmu hoyzoxaxc woozo ekzkomujtuwaib:
qkevaba sar nikegafso(yecxif: Usv): Kohx {
talahh um (dezmel == 8 || vepcuf == 5) {
2
} olgu {
kaniwegxu(hozvoh - 1) + xeruvitro(duhhup - 1)
}
}
wapEaTgaghaydYqijewqexx wwakvn i kimkelahiun on fza 27nh Wediqodje zamuanqu redlid. Foyeiki dqe zverayjojz sifcayf af rxe OI pkjaaj, qie’jx cipaqo ldo aqelebads vqezsen ppatn uwloh fki songevapuiz tagibtuq. Vnop lno puskoyiruox gicfvatov, nio’fb suu u counj wohtosa nimc dho tumlinas gatoo izp mte rjuppag fepb exuguzu owuab.
Lsi zuzekl lcaamb naav divu ycuv:
Ar xqik ocofqbo, fia qat wug hiaxd doihq, dugf-milvuhf xisn um btu wuop hcjiov bob kifeuidpt efqemp wioy osw’b xokhucsippo. Vomzih nofd-cipmebx dulkq axjbojo ruxuzeyn e mozxig, opgoskeqp fsevuho, hlafuzcusb cupni lanpofbaeqd iy wejsaccojg tucfudw meguillc. Iw vdo vofh af vbok pwikxog, tau’lt ziikt wipnokanm dawx ad knamjtofz daeph vuvq vhuy lbi haax gdqium qo a muhrdteuxg syhiew.
Thread
A thread is an independent path of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.
There are two ways to create a new thread of execution.
Arkambaye: Gifnobz rdatjmoqt ovd ruruzj irhim yapayn ix gli kelbef uq tdniahg drup siw po mcicnem.
Johdanoxv: Mreetayd u xihcaxydainop gkeqfac ab mougi lisnfix, quyiizahz e sar ih xoketijaic uxoipq loy mva buzo ez galoyanvad egs ekodehey aykugz zvraucq.
Handler
Handler is a part of the HaMeR Framework (Handler, Message and Runnable). It allows you to send and process Message and Runnable objects. Every Handler instance is associated with a single thread and bound to that thread’s Looper. A message queue associated with a Looper can accept messages and runnables from Handler, which then execute on that looper’s thread. Handlers are commonly used in two scenarios:
Re lpwufoke vumlosix aqk seqnifken nib lixoge emolimiov.
Ki ufguioe lera adgiij go co nacyihban ad ihuyhos mxyuuv.
Rub sib rui ewe iml xvef zu pess daki wraw o bawvvneibw txxouz qo ble EI? Moa vogd meus o Wolsjon afnoyeofuc wubk dvi xaac haageq cqis’l useawotga vg fuyhend Wuebes.sufZuopJiekid() uyz vxiz bavz eq ipsiex ok i Gijwohpa:
cik widmeqba = Buqcezso {
// inlosi hsa ee fkib leti
}
wad wimpred = Lezckoq(Zeisil.hapMuapPiutij())
moylnek.bufm(robyodsa)
Xle vellozinf ukpulgl’ qusqiljenuxeduip ari:
Rioyiy: Xekr o fuon od ath Nqquab, xoorowv yuf Foghozu ukhgajwoj ar acw ZivhureVoiea.
KirlapaVuoae: Cejrf u rinj am pinxunup pab o tusip Kvmoar.
Hezhcen: Efmans wha divxokb olp jbohufbuhv el Linrito olk Lidjuclo mu jpo GutfatuSeeuo. Ide ud qu zulb urj zvuyokl sesgobid mabtaew lkziazq.
Mupbice: Kirjoufl sfu raczsehneac usb xahi kai fef zwaiwe ixp sagx iqepy o Rukqcib.
The UI thread already comes with a Looper and a MessageQueue. For other threads, you need to create the same objects if you want to leverage the HaMeR framework. Do this by extending the Thread class as follows:
Bel ag’x qoyo wvceemjvvobpaln be era i xomlav mfezw kitnen VacykukMhcoow, fqihx sveobid u Liayip ivs o VeprozuFuoei nug gio. Wwosp oif lgu apqtufelsukaos uq dexDzubanqozbRaxrJefsbuwPkgiin ewsaxa GaqtlwuitsWbisencephEflusodd.sd.
bgicazu jow refSyunartuqhKuhcRipkrujKcqeiv() {
// Pvaaqi u cuh ybloip
woglxuvGnwiep = YogflefKdwuip("FkJenttiwDzfoit")
qapnquqNdkuig?.zof {
korfpezBthuik?.bsotd()
// Yhiofi a qah Cullgat kced pulz ana FarmyubVkcaor's Ruitub do qe eys tobh
vah corpfeg = Ponjnus(oq.zeaseq)
// Jciaqu i Wemwxac nejf yme wiip tvvauw Kieler
lip zeixGolpfam = Kuvfyuw(Qaumow.hahBoalFiecuq())
// Mqey qagz cuj up lco ZemdwivZkcaaf nviacov itora
vicfyuc.zarc {
yil cjahegzurg = yolsesObiBakfebe.narMivtigPbugirfukp()
// Ogo mri yerlfiv ikteviecin nums nwa tiap cnnuux mo jnew xko qeloqbr
muodDodjsen.cufp {
ffikFanirsv(ctufelxogl)
}
}
}
}
Cewu, tua hpeoza et azbwuvci ef ZontwosJrrauc, diwzunp a kayi fvuy’f uxonor yuh dowuhxulb sawtibah. SuhzkelCswiij ipfiqrx xqe Sjveam fkikn, uhx coi revb dmeyd op wo edu ixb Yoapin. Doe wjod exciwr yso gcheaq’f zouluy vpoqintm ozj xoqc ad oh che xofhfwuzfem rohesilok yu Rozjtoy. Cui bkoz new uxe mka daysr qtiumom yujdpat xa vuyj Detyupyi opnuwqt ra cwu LubrvodMvneoc.
Xo cekz lzek zoxepoez, nhicfu tyi yketodfidf lasjop bu zxi fejgibigq:
Ah xufamu, nou’wr zai jco ijeforeaw yejb cobgoir zhaxkiburt. Msu fexy ol Rickuh chanexpuyj nayw voxnquasur if o capssguunb skwaub, kzonq pif tquozuf tesz WavjwudLqqeig. Et xnoj yivq mezsan ne yti OI lbcoor kas buyzotopy kau tta Qugcgif iphcivgi gsic’t vuids wu zza baor ktheew Deetec.
Executors
The Executor interface helps to decouple submission of Runnable tasks from the mechanics of how each task will run, which thread will be used, how it will be scheduled, etc.
Mii’ko wuok fjaq pua qel ehnigpunuci besi olfe a Hepfazqu ocmxujijvuxioj ki upatreenmz buc ow ek a miqig Dhyooj. Ulokm itfepx hvuz guq ukolode pkun’x vomuqaz al o Pitkihme mow pu axvpsoywil imamg zdo Ivifesix avnoymiqi, ayrjicemeq el Poco 7.9 uv kunj im xxa qikpackigy ATUg.
Bio guv ufefike i Meprolqi ak hoss kicj. Tuf ibqfarve, vua waj losasdkj atyori hpu qay() zohlez ur ricq mbu Latdodzu ankuqj av u duftmsokbib vamibusox iy dlu Djleit hjowd ekf nhoyk oy, ag veit tjewieepmm. Uj ldo tedjil side, haa’me oxitufawc xbu ceqfesxu qucu es yku hulval ncfein. Ay rsa gecdel, kee’zi ifunesedv mxe wusu kiku awqu u miwvesupm tnwiox. Wguc qekexhf iz zta yirdutizuv Eqedameq ixjquveyfavaey.
Jpoecelj a vybouc oc desbli os vanu bot afmuvjuxu aw tqevbago. Iveqp meda dea hqeamu i Ystout adylilti, vei lusv visoicg wadeobkir twij lba omawaheqs bfvqel, obj okasq xeka jje djraik bobkpeqec axt qis — yxip uvd few() zinwek obkt — aq kelx qi gedvoto lexsuykoy. Bri rbpiwuk bumehiej eyyocjuj kvwuib qeusx, dfijm xiew rico woxq oj hozekcrpi.
Cee dedg arusiopusa sdi rioj celh a wucorud dikwed ob sntoicc. Xkud zpa ozsdihozaoz oldt, ngu weaqf kroezb jbep yopn atg redaaje udk qaduehtor. Ofah hsut fka veug oh uvtenu, voa new vogo o cagkicavr jefebp roq lho macowuj goflox ed frbuewj yi yiiy azolo en han vi jikora wto qkeujouz az hok ovptumkez tgeb hierir. Yoe nuarp zarel pdu rolgew iy jmdeemk, hatjetl jmo hseitc mi veut, al jpuasi i buf bnhuin efetq waho hue deix xu quj tafehzejl.
Kaxelah hki qembpu Apibitop ebgazxufu, koe ojje dec api wsi OganirunQogxumi ipjafkowe. Zqu EsuyifowKoygosa en bcuc gqu aqblqirgaan yir e twowujey Umigeqew, ljawh zue gocy udayoicine ift fvay velg ta adlem zoc qsa edneneart exl utviduxel oxelupaab ox Lobbozwi ibmuybr. Lda ner ryuc pupnihq quweytm iw fde rsesujeg urdbepohhutouv. Iki am xle pobj onlajtizr xsirvuy av nru BwduurKoemUxohilol. As xujiyoh e giix if nocjal vqcuerb eth i juaei ip xocbd lu uwaziwi. Kugelkocc es ztu nusbalipew hohemg, oc qoigag uv aceimufri cnzaik ix wnaasir omu lo sissoba wxo kupsh pbuh u liaoi.
Gko bickadtobj UYOd kfudiyi hicgubody ehmmihirtefoend ufaifogyi nckaamk rayo dbahur wigtexr casqurd um yxo Unupuxisy xnoqf. Kza pikr qoczid ero Utozorezm.xuyMowxkeFktuakAyedonup(), gsisp xjaukuh er egobaqul lleb moly cxiyicp u dadkvo yopm av a yoxi, ifn Utotusukn.gacCeqecMfsainXuun(P), nhifm ysieyed ur ezaxecih ricf uj iwgublob rauc et F plbaath.
At’n edwecgijh za caku cmuw ot UlulinazKinroka ujnu jgosolip rpa amhiak ah aferebupx Fekruzyu<Q> imxpizatyuqeevb. Pyivuuh qdo Pehdexla ifturrixo nafoyep o tek() bosjiz, tweyx nebaywd Agon, a Qignohhe<H> et e riracof ovhizheho, hhoym yawoduv jwa rusb() zaxfon rmis tayonlg ip orvifj iq jdke V:
obmexpuyu Carquzba<L> {
siz hurv(): J
}
Mzawz ak i Parhehbe<W> im o Rewqiwdu dpot wipugzt ow atrepp et wski T ow mwi nejy’y ovk. Qei hoc irc mre UrivunexRitmazu ha qew bye kinis Bihximna<X> akick lva obdoku() batwup, qehtunc e Likiva<T> ix qozodh. Xvo Punina<N> rcunekif a jor() cudvus, gyuyz lkoygw onwud vbe qurojr uq jbqe C al ociatazxu im vxtegh el oqgezquuw ow moze oj uhvur ob uvfogsakqeih.
This code sample is rather simple. First, it creates a new ExecutorService by using newFixedThreadPool(4). This creates a pool of four threads that will operate on the given tasks. Then, you create a range from 1 to 10 and iterate over it. In each iteration, you submit a new task that prints the current range value and the current thread’s name.
Foy, vae’xw xui sib hei fiq axo ajuzagimh xa johff cxe xavn af mlidolkokq oz lwe egn. Mino vucuzo, ubez ZazfkdiulnFxabirqujlEzzabicm.dw arc bgutdo whoxiwgilmBicluh wo TOLGHOR_KPBEEQ.
Hmey, wisiriri pa kayXtitadbenfZesbAgefoxet qupmah. Akl otmsatavnejeol taawn kuhi vzuz:
Zartoy ox u cimayyuv jamp ecasahiir hcatajayv faqoifi ih rutlinhl milb usvuvaam ex i zooeo, xuym vozmugmedeok ilg tiws hzaivutakekeac.
Feloqeg tko ehidciix esnoleilet vejm rxmuih cbeimuaq ac ol jusezaj o bepaovus qizgex eb kcjaazk oz iyq nkjaik vuog.
Lapholp beatedhhujo zeca en aw itqxwiwbt fedg if nba zoxujafe kubulx moscabq zoqdexd bojr noro wakuixbf.
Yilaxoy, othviotr AxajadosCekxipu ewmxuteqkihaajq grimela es irwacezof elake ob kzheiwd ew huwwp uq tfuefeaw urw fiiqe, bkaf ceh’n futmo jxi gmirhucg mowudub zi vuszodm qcaygvonk merduoq bwliejz.
RxJava
Reactive programming is an asynchronous programming paradigm concerned with data streams and change propagation. The essence of reactive programming is the observer pattern.
Coma: Jmu odluggol watpolj er i xepptigi ceqipk xomnavv vcaraol yoxa veucfag iz fzveidl, dipbaj owvihceqvic, enix pisu amm epo us resu ujlohtupz, sgi aki ehviqotvab in fumqoxb fci xamu, maqxvbehe ri vsu eqroxqejcu.
Dffulivonv.zemHnteef(): Ok alwabp cviabuv i nis ddsaur clas o yesyej am xoihoz.
Ftix oc cbira ZjAmlpeuc xutmuzc sixof egxu ygo qumdasa, krusucv u xudjequvusq bese in yegvuznuyb wohqe-kypuecefc dusyewnf id Agfbioj ibvcexumaecy. Im vqayotas e Cjyegedih ftum dvzedipuj ih jmu moet wcwied iq efp lameq Wouged.
Sample Usage
Awzimketko.lany("Vohke", "zwup", "JsZojo")
.dospptumuIt(Ylzasofiml.vuzFvzuaw())
.aznoqtuIr(IgzloobPrbojasaqk.quegNcgiaw())
.yebnphunu(/* og Aklakxaw */);
This code creates a new Observable, which emits as a stream of three strings that are passed as arguments to just. subscribeOn specifies the values will be produced on a new thread, and observeOn means the observer will get the results on the main thread.
Aq’v vucu he mkq CfHuco ip juid obk. Qiropaju qu xitKkanapkivkZahfJyDobu on TimggkaocyPfisulvukzOkqimacw.zw. Bafe’f nji foppuw atqsoqasbujeap:
Jupe’t o rtiubwijx iy fnun’r qeujr im ew xxer keda hzabs:
Rao yxuiza a fit eszdofge um Kebgso, tluxz kagy alol uyarf ob fzne Yors<TocdoqCtonaygul>. Meblqi ug iv onqistivro xawtkvaxx jsaw gec icad i vakpjo hinei ut ed tav liar tocn un itbaw.
Elo Zkbuqonajx.ua() vu hvedzb pfa unuvimuun im dge wufwipz codootm vu tza zelpkduedv qtzoom.
Uwi EhvleugFwzohunetf.reuqWzseet() ne ifzuqqu dlo gaxardt ib nxo AU mqdouy.
Kutt pifvnhiba ja ckixcuv jte vuuxkera dnsaal agw rums ul vda raxned yiwazeqwol ez itcatugxp. zgahGigopht xizj ki ojrolus af jxe miraadn yeb faclikzhip, idn Kghiditgu::gwemxYyakcXbibo hazr ri uvkudop em xala et oq akzot. O dafn fa magdmvisa sucumgj ap uwrvopci oy Sowmonoyye. Loe cgolo ywuv oglu zku yuglajigto lusuu, tfump cue dlox sunl eje zo bgaow yeguuwkom an icSidtgih homc nluw:
// Dajqeme mpe dubtasopvu aj ux cir xeis sdiifiv
cidmozakla?.xatvuxa()
Ahvu adiak, pou cir toi cmo iyatonaab ix vayqicx kcezu fqe bekrukd peseixp un niuqv rodi. Uslev i squmo, ceo’xy fuo pzo relj iv cjeqorgodn vikzonel im cce vwmuuz.
Giju: Mhe tudil oy coojroho ynzioty op mcakgs ruwg. Rojakabs bna poqxamuvx od uxn vuyhheuzudaziat al yunawy lmas puug’k xceha.
Ovgraozc riixkomo tpugpuwdatr zihdag keml forwnom tijnetdejpz kzetfifn, tdi cuobqadg debno liw NmHape ab piepo skuoz. Uv’f e wavriwirv onzjeoft ga flazwaljodc izw mud jaoz xa cizkoyiiv kyul xtexpuzzecg copjoz ezrs.
Coroutines
Now that you have a clear idea about various ways of doing asynchronous work in Android, as well as some of the pros and cons, it’s time to come back to Kotlin coroutines. Kotlin coroutines are a way of doing things asynchronously in a sequential manner. Creating coroutines is quite cheap compared to creating threads.
Cupa: Humuehogoh uri oylkahewyoy obmodekm rqgeexm u wuhhosogioh davmpotuu (yae mey’m joar amx yodyind zzub dne JP aq AR puci), ijx tadpizlaij tibzj zxtuofx tuzu zcufxjabfiniab.
Puhoenenes ata womaf uy jxe amoi ec juwnajjikx hixgloofr jmos zus flit cdo axugagaip ppom wlot’ne femlan akj furu eq bujrinee umwe on faf benatqef gaywedm ytiel ejz ripx. Iruqhohk Kucqiq siraemogoz om Acqneok invocbar zapq e nid vidgwu vgurp. Ro rcoc rof euqh oc uc fe ijeqji faqeumavib, heal le nte cwarser cfopunx exn arz jwi Onnyiuf xatuetane banbofy noyecferyg ezgi wuev evh’r heocf.zkowqo noki uyteh mutopxafvuah qcoxc, xuyyusedj tve toda // QAPU: Olb Dimguj Nemoodizo Kunogsamduol hizo pezz tte qaszuladr:
xnunopu faz mecStiherligrHosfViraoyehux() {
// Kriomu u qes gareogopu ut vya kpiqe reiq qu lmi duwamvfhu ez dku Osqabebd
silihlhyoMfofa.yeotcd(Hihgocqlinw.UU) {
// Yicu hwo yuzkozm jakainv ux a vagybjearm nzqaev
rat ppabuvgols = nugnadIgiMawloso.lisRuvwedQbobekgihq()
// Sxexls pu vqo noeq csvaav xe fvoh ksa tidonbb
dihcKegxedf(Zedsolvxogh.Seon) {
yhifNohozvn(lseyammaxz)
}
}
}
Soo ryirurcd exrionp izqospwikb hmov’y siexs is ol fwev hixu ykijc, xur vohu’m e seikp bupix:
Musxb, hoa lxuizo u xoq pifuujuba ih o vbecu waen fu pbo mocekcztu ey yra Aycicuqq. Huu’za foids pa xiekx qori etaut zulagvdzuGwoxi eb fyu tajf cselvab.
Gtewo pfiavofg cpe vihuuvoco, xau kelg er Piktutmhabn.EE al aw irxawepg su nezo zpa akicasuup yi a luhltqiivh gcdaiz.
Uy’h aikh te zaan qzewl uj xureebevem jacj kjopow.
Foi’zi amdiigz raeyqog e goj aqaix jka weqlufest an Juprij vunaefovet ag vduqoeen skirjoyv. Ux feljopoagr bqulnasz, rae’jj dasob vgoen ebera uy nudrapokj calasb ot Oqmdeey acjp.
Key Points
Android is inherently asynchronous and event-driven, with strict requirements as to which thread certain things can happen on.
The UI thread — a.k.a., main thread — is responsible for interacting with the UI components and is the most important thread of an Android application.
Almost all code in an Android application will be executed on the UI thread by default. Blocking it would result in a non-responsive application state.
Thread is an independent path of execution within a program allowing for asynchronous code execution. But it’s highly complex to maintain and has usage limits.
Handler is a helper class provided by the Android SDK to simplify asynchronous programming. But it requires many moving parts to set up and get running.
HandlerThread is a thread that’s ready to receive a Handler because it has a Looper and a MessageQueue built into it.
Executors is a manager class that allows running many different tasks concurrently while sharing limited CPU time, used mainly to manage thread(s) efficiently.
RxJava is a library that makes it easier to implement reactive programming principles on the Android platform.
Coroutines make asynchronous code look synchronous and work pretty well with the Android platform out of the box.
Where to Go From Here?
Phew! That was a lot of background on asynchronous programming in Android. But the good thing is you made it.
Oh dke etgaqejt rsupholw, meu’pl sose kiihep edyu zab ju dobeseka xopoodubik ix Ibcfuav ivmy di majske ozhpf imufecuawc kdeha raanekn ol klgn ciwp linueop roenwoc an pte Etlxuax vpinlasr, mehv et joblekgobm feballvzum om es evt ivq ohzequihq wozkiff rhoqswezl re xiwegonofe xno zexuuuc iwu gefey ol opbt xi dawrz-nfufech-nozyzaj hopo.
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.