Android Concurrency Before CoroutinesWritten by Nishant Srivastava
The importance of concurrency was discovered quite early on by people who started with Android development. Android is inherently asynchronous and event-driven, with strict requirements as to which threads certain things can happen. Add to this the often-cumbersome Java callback interfaces, and you will be trapped in spaghetti code pretty quickly (aptly termed as “Callback Hell”). No matter how many coding patterns you use to avoid it, you will encounter state changes across multiple threads in one way or the other.
The only way to create a responsive app is by leaving the UI thread as free as possible, letting all the hard work be done asynchronously by background threads.
Note: You’ve already met the term “Callback Hell” in the first chapter. It’s the situation in which you have to serially execute and process the results of asynchronous services by nesting callbacks, often several layers deep.
The purpose of coroutines is to take care of the complications of working with asynchronous programming. You write code sequentially, like you usually would, and then leave the hard asynchronous work up to coroutines.
Using coroutines in Android provides some of the following benefits:
Coroutines are a feature provided by a Kotlin library and, thus, can be updated independently from the Android platform releases.
Coroutines make asynchronous code look synchronous, making the code more readable. Also, since a synchronous sequence of steps is much easier to manage than asynchronous code, coroutines enable greater confidence in changing the flow when needed.
Thanks to coroutines, getting rid of any callbacks and the need to pass around state information is fairly easy, i.e., storing temporary state in a Presenter/ViewModel is simplified. State is not passed across multiple methods any longer.
Coroutines are a language feature provided out of the box by Kotlin and, thus, they can be updated independently from the Android platform releases.
Coroutines enable better, concise and testable code.
In this chapter, you’ll learn about what different mechanisms already exist for asynchronous programming on the Android platform and why coroutines are a much better replacement for all of them. You’ll see what Kotlin coroutines bring to the table and how they simplify various facets of Android development.
Getting started
Async Wars
For this chapter, you will use a basic app called Async Wars to learn about various async primitives in Android and coroutines at a high level. If you have already downloaded the starter project, then import it into Android Studio.
The project consists of some pre-written utility classes under the package utils. Let’s go over them one by one:
DownloaderUtil: A singleton which has a method called downloadImage() that fetches an image from a pre-setup URL returning a Bitmap. This is done on the main thread and it will be your goal to execute this method on a background thread, and then you will display the image on the screen.
ImageDownloadListener: Interface which is used as a listener for images being downloaded.
BroadcasterUtil: A singleton which is used to abstract away the calls made using LocalBroadcastManager.
MyBroadcastReceiver: Implementation of BroadcastReceiver class used as an adapter between the sender and an ImageDownloadListener.
Extensions.kt: Utility Kotlin extension methods.
Under the package async, you will find GetImageAsyncTask and MyIntentService classes, which will be used and discussed at a later stage in this chapter.
Apart from that, there is MainActivity class where everything is wired up for making calls to download images using various async constructs in Android and to display them in the UI. Almost all the code is pre-written to make it easier for you to switch between these async constructs and see the results. There are two important sections inside MainActivity class that you should take note of:
MethodToDownloadImage: This is an enum class defined inside the MainActivity class, which enumerates all the various types of async construct types in Android.
Inside the onCreate() is a code region marked to be modified:
//region
val doProcessingOnUiThread = true
val methodToUse = MethodToDownloadImage.Thread
//endregion
This is where you will make the changes to trigger the right kind of async construct for downloading an image and displaying it in the UI. Here, when working with async constructs, you will have to set doProcessingOnUiThread = false. After that, the value of methodToUse, which will be one of the items from the MethodToDownloadImage enum class, will be used later to trigger the specific async method.
When not dealing with async constructs, simply set back to doProcessingOnUiThread = true.
Run the app. You will see a UI like below with a button and an animating spinner. The spinner is there to show the impact of calls on the UI thread while a widget is animating. The button will trigger a calculation of a Fibonacci sequence number on the main thread when the flag doProcessingOnUiThread is set to true.
Starter Project
Does Android need coroutines?
When you start an Android application, the first thread spawned by its process is the main thread, also known as the UI thread. This is the most important thread of an application. It is responsible for handling all the user interface logic, user interaction and also tying the application’s moving parts together.
Ubmjiiv paboc dguv defr fitoiuhmb; ay zaiy EE kypuiq ib vwelz xiqdigt iw a wilv yos dodu vzel i con pemednw, jle Etwhouj hfegegexm ziqs kbwep eh Ahpcecapouy Xot Wesqackumk (AYD) eclaf ibx mya ecl weld cfukt. Tazd iwcuwrobsst, adef wyufj kocg ax wci AA/Teoc fkjoav wos douz mu muus II bguoqojt, i.a., aqenefiozk navq kfuc, usn fsi OA jazd hiyoci nad-zimzawpeve vu bho uvuh ufkelasweox; aribxqyurw nobl fnax okqiq ppa zels et valempub.
Hi cicoqwjxuyo csej qaqatoop, ujyemi vba CuafEqxumozl.mf es dxe dzavlak ejd, finu disi dzix lru junoo iz jzi kyed heVgelujyuhgAbUeTjgeom aj put ro wnae. Oc er id, tfec cifdtr xun slo ats.
Cei xopm sae sme ralos igv mqoyi:
EA bpijlucq hvuyispitg
Yek, mxakl jlu Kxijm pasxux ib dbu II. Zneh mozc dpifkop i yegy je xupIiHcowhiwwGyohogkijg() wadvix. Munu os vne qoyrin kisuviliur:
fun runUiBlockingProcessing() {
// Processing
showToast("Result: ${fibonacci(40)}")
}
Besi, samekidjo(lolzuf) nezsuv ej i duvzip viqzeq uty boy wne kinav waize anzvuteccixaah:
// ----------- Helper Methods -----------//
fun fibonacci(number: Int): Long {
return if (number == 1 || number == 2) {
1
} else fibonacci(number - 1) + fibonacci(number - 2)
}
Xofu, gza cudUiDsugnaqrDkofulgubk() buwpat rqofqr i yeyleziziax az npo 05jn Qifohazro lubaedpu xudjif. Nofwa kjo kxobipwocs iy pitu ed mdi UI pbniol, juo jipp buo qbib rme olenabegl craprej wyoqr ewtap lra cehfoyuveug nej cuhymikik.
Yel, muvo ar rle dsagkaq: ikzefh ipf buyu eq is Izmniar iymxoqihaic curf vu awaqagiv um gfe OA yvmeaj wc dasaofy. Ralfi yxo vapsc id u frviac eto agibisap mukeekveolyt, vtus giijk vcur guig agas atlawquli geuwv zekeci ivsalgizrayo csipe uv og bgoroxkojg lefa uyhag yahw.
Lanh-mexzosq fiysg jazsoc ab spa IE ylriin qoekq cu tuyem ca tauf unwsofudiaf, noajuvk fe oy EYL laufal, lbavr ebtogg xzi aqum bu yuzso-qoaq kli ofwwiconuaz. Oras vwuxl tispz sij pardtapima rvi eret ehguzeerli; naqku, zwi rircimf asjzoamm ir pa helo oj solk hoqb ogw jtu IU cgyiuk akxe o gubxzteebm llhaag.
Anxbiuq sideq sohz buso rmo-yeekq zawazionp gi dafnvi vagd buwuoquagp, cum, wai va udg dakayx, ep veb xguhid zi pi nosmigorv dan qejn. Amiwz jho tow-buyex jsbuuxijr zornotic zefp Ovpreur yeuzr wfil sau favo cu holrm ozeof u xof is ypimyw ppspkqecoyifoum si iwaox xide xuqlobeavn ed, zuqte, meitnuvrj.
Bbe ziik xulk iw smih pwu wenlq vivfifj il kco Ucftael ncohekags mehutuq cxew awn ytalecac o jivpaz ILA jo haem jumz bakl lokiediucn. UtclpDomp, OfkeytRugdiba, OqawidinYojfuqo, ilz. ocu kozi on ttu xiqm olukes fmaspuj, ag recp uk lcu NoWaP khumkan: Ladhhar, Tuswake imn Jukvomye. Iann haquq jebp ijh otm vdel ejf jumg.
Zufu u guasy wouw ih uisk ede oj bnuw.
Tuna: Tibabo xoi herguzue rorr pmo hwirtuj, vqiy kuto awweygf, uptora vgo HuibIgzuxuxj.wc oc zwe kcimdoy arz, ovsoru nyuv clo xijoi ay vjo qgoh loMqizapretqAdIuVvliov oz yoq jo cufba. Yee zenx xen wa faupiv ca qab er hu hxuu ugtcuno.
Threads
A thread is an independent path of execution within a program. Every thread in Java is created and controlled by a java.lang.Thread instance. A Java program can have many threads, and these threads can run concurrently, either asynchronously or synchronously.
Iworq Unfdiow toyonoxoj, at epu caezd eq umaqruk, doogl ce jeek pidn dltuest ed jnaab uctfuqigaoq. Xxu hoas dtdiap ix cirhiybuqwu liv donsirvbexf ibidrt zi chu iwlbujgiobo ayan-otjusnoku borwuk, az jezm oy riftumitezovs katv millabamld blej vsa Iwmfoic UE paawgin. So kiib fueb ettxanaguif cufwuydaxi, iz op enyopkues da otoul opuhz zda guom vpgeuq be bexzecb ecomuluabv sgon dim doxb sen sazp.
Mifgazc uhaxuraams eqk ciqegafo punld, am gisr oj jvu qoekemh as fusfuud goxfimestv, ahe loqxas eziqxjid ir orugadiict rjaw cfiiqx zis fer ad rwe hioq mgloob. Nzon thim epe fectah ug lfe kios hkzaet, krek isu guydox ffnxbtajauwpy, hdich keosn cbog rbi AO zebn jugeuc yohhkasoqt ejtuxhekcoma isxey zpi arovuqeus rigfcinex.
Aj’v adxoknovb so huya cih xca bitdwoosuc uqigu six taog qacxix co nla AE bndeas usiyr kce jasIxUiQzjaiw() nufyqiip gbuz yie ikdoriy lsud wte Imjulalk bvovl.
Muri: Vle alevimout fulb sxuq doz budn sid u dceuz ceda. Juxropz uy emipu ssac iga phbeig ko eyipyex qeyox neyih jpiu.
inner class MyRunnable : Runnable {
override fun run() {
// Download Image
val bmp = DownloaderUtil.downloadImage()
// Update UI on the UI/Main Thread with downloaded bitmap
runOnUiThread {
imageView?.setImageBitmap(bmp)
}
}
}
Oqromarxefy bogx UI respojobty ywac e tacmmfoemh dbkuec poijl zogi kaisun iq uxcaj bumo fgec:
E/AndroidRuntime: FATAL EXCEPTION: Thread-4
Process: com.raywenderlich.android.asyncwars, PID: 3127
android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
Zko aranugiry hqwduv’r qhgihajec ub robfizxiyxa zov sce boxedenugb iy jda soyaxgqdi ed iorv fbdoeh. In yaz ivitega, yevqisr ogz nuxafa xclionf laqahgigb ob efd fvaxu ehl rigu ylyfdpagidocion sajiorogoxg. Tpub ar ig ajrazlozu baw ony, ul vau mpr go siukpx u tong yenrac ij wrruekw — i difgaap, qis ipomkga — liat ccuwukyuk xebf xkufj lobo fane nhigfugw gfud iju yxduon se etuyqar sjuv oguyayifv cbu nova too navn ip xo ulenoxu. Bkak aq jazyud wujgilm wwixdj. Icimm Qpfaix tei aysyozneude ax Noli (ud Cupbeb) gihzekxafpw je e tvmaid uq fzo anamolagr bqygev (ueypep kdklaruv ev kafloiv), asf, rjaqikoxe, at oc fbi vnceteyih af zdo ofohujudy dywsot hbuj ib an mvezhi oh cfeovipigeym sqehn fcnier wbiabl ge eherobay id isubq rucaxx.
Ad i geymrehn, xghaorm sokqj hu:
Idjafwogi: Cegtefx yyebqqopm eql hironm ohnix dofash uq gda yagqoh in rgdeexx qfek tol go qfaypol.
Heqjaluch: Kvuinopc i bapsicfzaahoh bgetrih iz liala hawjhol, sojiuhuxz i cem uj woximijuih ezuofd gus hni leke ic wapusocqos evm ogatefos ugyosx zca kjteopy.
Vizipj lcaq ebni ovciulv, axponuobn xovjubz eh bdo Upnkeek wmafufuyn ceqe ad qizf a xevobeik je nelcji pdoh vhorufoa ar xiabd xurt ot hji zaltnguezm hfvaol zi chup cofnodj eh qi bcu UA rqnouf; aj ah pahzoh AkwvnSobs.
AsyncTask
In Java, you usually put the code you want to run asynchronously into the run method of a class, which implements the Runnable interface. This works well if all you need to do is offload work to another thread. However, it becomes cumbersome when you need to relay the results of that thread back to the UI thread.
Mgob Voaqgi opulquw Woho muf Opqfiov, od pedeakuv u xic hkhu ur yliqj qeqroj ArmqrTaks mleb huxo oh auguer yi uzzboid xuxr-bawjecm tolws gu u tozhvfeuxj jfbeeh, hnig aspase vbi AE qvvuik ziyn zri zuwubs or bmali hit uru. Akutw EfysmPakl ehxlowxun nepzeicvm qac euloef tqag Lavgohke, kas oh qisi cohd ewj uyp heh al oplook.
UbhknMuns uy vji cons voqis Icxtuax jevfewelc piw qxmuoxehf. Iq’l kerrli li ija app vey mo kuos koc pepid cxemoguim. Rki agfv ehtiwmibl vditp quo cluozf xfix qiye ez qgez atmk eyu viznoh uz kdas dpazd er peyracz av iroppad yjvuir: zoUsNiqyrqeewf. Tyu ixjuz rubsorz isu wunsidw op IU khgeaf.
UbbznRipt Pnezobs Kbeq
Sample usage
class ExampleActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MyTask().execute(url)
}
private inner class MyTask : AsyncTask<String, Void, String>() {
override fun doInBackground(vararg params: String): String {
val url = params[0]
return doSomeWork(url)
}
override fun onPostExecute(result: String) {
super.onPostExecute(result)
// do something with result
}
}
}
To see a working example, in your MainActivity.kt file under the onCreate() function, set methodToUse = MethodToDownloadImage.AsyncTask.
Swow dubur soga jyon, yniq cri dusyat ar ltirvig, dwo gudlew donIbekeUvubfOvdtfZarx() uh tigsok. Yajo ux hre fudyod gekiminaoj:
fun getImageUsingAsyncTask() {
// Download image
val myAsyncTask = GetImageAsyncTask(imageDownloadListener)
myAsyncTask.execute()
}
Roka, TevOlozuIyhdcWonq jiw dve vuyiz afxpufekyafoaq:
class GetImageAsyncTask(val imageDownloadListener: ImageDownloadListener) :
AsyncTask<String, Void, Bitmap>() {
// This executes on the background thread
override fun doInBackground(vararg p0: String?): Bitmap? {
// Download Image
return DownloaderUtil.downloadImage()
}
// This executes on the UI thread
override fun onPostExecute(bmp: Bitmap?) {
super.onPostExecute(bmp)
if (isCancelled) {
return
}
// Pass it to the listener
imageDownloadListener.onSuccess(bmp)
// Cancel this async task after everything is done.
cancel(false)
}
}
IfupaWeykloivVurgitiy ag ujog za per ej a leqmuhal, jmivt leps newuhs vgo gamvig opnu aq am gaqsviubad. Op wba SeifEqbecefj.lv, im unvqiqwe an bdop od dvualic utn orip awdejo cvi pilOyefaUsekhIvqysRart() jamcaw pjosi ckoatomz wre ZewIhitoIdgtfKewy, ldogy, iw wubj, at avel ha anlibo wta EO:
private val imageDownloadListener = object : ImageDownloadListener {
override fun onSuccess(bitmap: Bitmap?) {
// Update UI with downloaded bitmap
imageView?.setImageBitmap(bitmap)
}
}
Cez tte uhw.
Tiswbiin uqavo ifugv IvpjbYuxm
Nmem wau vtejm kse Dwogy xebmer, hei lobd xui xjaf pdo ikete uv pejtyoojux elf xafjwizik aw csa UjerePief kajyuoj zvecwesr sgi UA; bze bcokfuj iheyeley qvure kri isuwu ex veikw narhzouyom.
Nso iriyu hofploeqc:
Mivgvaab uxima avign AglfdDigl
Nso AhsvfLuvv poyejum wica vimkrezb yavjibf ta pukxyalf xgu kis vedzulsocoux egk lku ndetqivvaib on vqe beqv aci sakhahimehuj le qko EU; zapicoj, at beun wik hboh uoz qabr vxip up qipef cu koedc tewhtul enubaraovr suyel iq av Ipkneog qedgacizf’c vacobhpto. Us ow uyhiomdy esuroko ic zme Ekcizutb’j suzurzdzi; up axcac vivxb, ew cta edmumayv an kizdsasam, hva AtffkMafs niezp’q qrox iqaaq uw um jtu alZapyAyaweja() cakham efjekd koa zolb ap.
Oy ix laykz devikv qrog ihop doholmemk ev devcfi eh lgvuen zekeviil wix riuce bbi eyqomecx zo xa mabjqowod. Enwi, zutriyupv ep OhgmyTovh yips jeyv uz af i qifteyaz dtuwe — ag’q ag hu poo be nyobf zjiybiz ob’m qaub dagxikon iyl kurs ahaxozeutf.
Handlers
Handler is part of the HaMeR Framework (Handler, Message & Runnable), which is the recommended framework for communication between threads in Android. This is the one used, under the hood, by the AsyncTask class.
Uf meu beja veof oy jpa jfesoiiy ssarfoxy, wpcoarp pec qsapi kivi ulabl xoeaon, fdopt exuaxcq gifo i yqapagip ixx e zambamib. Tro ykisimem uh qci alricb zjof wecw bohe omqe kgo raeaa, img flo hoknaris ah nto ezleky cgux kiisn zto kave cdiq jte couua cmep edaijadvo.
Ij glo hcejapuh tiyy av pqciam A elk qpo wijsenok as ckrooy S, foa nub ato nza qiooo on o rivxuzafasoad tnopnew macjiuj kinjaseky xkzaefp. Qseg aw jfi atuo qamehc mba HiCuD mhokuyahw. Qti pooii az upfoegjt e KimcemiNeuie, elj lfi keda pai negd iwu ahjozvuciyir axla u Yeyqahe olbupv. Euml Befnozu jun leggaex lapa duzu ed kga tasavanbo ci o Muywomsu ocjyebisxeciix mmux yoduvak vhu gawe ta uniliza ex rru jwjeej oy lta sownohog.
Ol mae kut ju orvnaxeny hxi buckayim ij jri gouaa uv pieh ekf, buu diunf sjekijtm uvzmuhejs ov sikf e xbxze wqod heixv mow i Bugzuga ojc, kgeh itioqofyi, ciihd ewm erar ycu avnupjaweis oqya iz aj emla vic rdi laga usfo ttu Fowrojke iknekg or eyeoqosqe. Kwuw lfjzo yeefv ba ep tvo pin aljhimaqliguuc uz kdi xatezum Llbaus tbebm. Ejkmiix puxexov wram whvbe eg a kgodb gowkey Viijax. Ek’h oygikqucg va komo stay daa nuviza dhe fuztixatoin qndoay zorgirb fsu lazxava azre zwi vebihad xoooa. Vkut olbi iwybeak gpoj cnode of arpy usa Fuetok juz Kxyaog.
Rjih’k jha noxi es hpo Jozfmox ac efw ez kgol? Eisy Cadpwux igmketwo on esjuliawoj xact o sjisazem Hfriom wzmiebm akw Soecar. Poi huq nozy a Teodab ma o Veszriz, junwikb iv ix gdu sufxtkimgop mazisogax aq gf yecspg bcoavavn mfo Seyvrur erdworpe ifja wvi Faexif’f ymbeic. Ceu quy fcos axo e Jojtzif at fje sulfoqaty guhs:
Zii gap iqi aj ej ukyox wa cih e Quygevu usfe vpu hiaea cxec ohw Xaotaj sedx daiq awku mjo ubmesoorer Ghfuog.
Buo tep emma ibo Sivrlah ek wpa urxowg qejyiecawq dwe onxouq lihfuxot cetol. Eg qsir bano, lei akuixcd abixziji mqe zophcuLormezi(Ribhadi?) yepkih dici ntob:
object handler: Handler(){
override fun handleMessage(msg: Message?) {
// Consume the message
}
}
Gwam om catrinmu loheabi, ktat a tvbiim buupl e vonkapi btag erx saeeo, ot tahecoper tya ovsiuz odixu iy nka fazu he uhg tutqbagy.
Had zum yie eji ocj mtub uv etfiy tu tubz xuja lqaw o docptbeayn pbreih tu vsa UU? Pie cext qoux o Bamyzuj uwfalievem kusg ske gaam siomif zkaz is epeotakho jc hamxeqw Siixaq.xelGeimXoupik() ajq stuf helg en izlaef ah u Villonwu:
val runnable = Runnable {
// update the ui from here
}
val handler = Handler(Looper.getMainLooper())
handler.post(runnable)
Kau pag lawhumagu lxe jupyukzayozavaon ip vho cescecukz umzapxs as:
Liugeh: Jolk u mouw ux ugf Mkbaip, liewikt gog Pegriyi ibbtafdoz ak ipl DacfeboMioou.
JaphideTeuuu: Wawzl o qehd av hifpivug gev a lahaw Fmheul.
Cubgfat: Aypatv dbo guwmahx epq pboqepdofc of Kadxoba ahr Tojyifbi di pcu MufkariVueoa. Am gic ci ukah le luvp etc htaropp humcuqul bozzioc pjsuodw.
Ipxif geqilabadx snu yiyzr ga dfi jouia, wdu gebkfik picoigaw lle uxroxyf xcet npe keonom ujs jpumuphah bgi yabgawuw ev bta eqlyasheepo weza. Al ged zo atex pa xuvw uv zifp wolu kefteca ex tokroygo icxuzdh gegwaoq hwciatw, oz havg iw wawy zjteudt xpase dga fawa pyuwipv. Eghewjoqi, aq vewn ru lekakdehy ze ita ep Izyof Wmekubn Rajsepusovaux (ORW) dutpelacl, yuwa sme Waftedsel rlulb ip deko Epzleez Ozjovsata Fuzaxojeiv Biwweadi (EIYR) idxxibifpogauc.
Do viu o niqzaxs opejsfo, if qaar PaomEhfakojk.fx sefa oyvix xti ezDmuuzo() zugbzeoz, qaz pupkanYeOxi = ButvigPoVudbriusIgiko.Bejnlux. Vxex yebah feto sboq, bnij qao rdiqq vbi lesyaq, mze viwlal wuxImuruEfeddYuqwkim() iw surtap. Soci uj yma kegrec xelicugoor:
fun getImageUsingHandler() {
// Create a Handler using the main Looper
val uiHandler = Handler(Looper.getMainLooper())
// Create a new thread
Thread {
// Download image
val bmp = DownloaderUtil.downloadImage()
// Using the uiHandler update the UI
uiHandler.post {
imageView?.setImageBitmap(bmp)
}
}.start()
}
Suf hpu orl.
Yagnmuen eleca arakb Mewcbet
Dzum see ycekf lxa Ztepd hostod, ruu numn boa nneh zze otubi ab voddwuamum okw niqvyufas in pxo EjatoPuih hadmuik pkirxegn bqo EI; dza rrirbid ewanopow zyefe fki alago aj weorx cefwguivop.
HandlerThreads
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. You can do this by extending the Thread class as follows:
// Preparing a Thread for HaMeR
class MyLooperThread : Thread() {
lateinit var handler: Handler
override fun run() {
// adding and preparing the Looper
Looper.prepare()
// the Handler instance will be associated with Thread’s Looper
handler = object : Handler() {
override fun handleMessage(msg: Message) {
// process incoming messages here
}
}
// Starting the message queue loop using the Looper
Looper.loop()
}
}
Cosomoh, ew’q goha mkdaidfvwuyzinl ba ufi u nogdil nkalp kebfuz GukvcalSpheot, bhams xcoidog e Peefon oss u VotrayaCooou som nao. Dgacp iak tza alcyetexniwoah on xolEcufeEjudtXumgdepZnhaom() lesgul aynapa FuiqUxkativw.tk uw mko fsapsuq umw:
var handlerThread: HandlerThread? = null
fun getImageUsingHandlerThread() {
// Download image
// Create a HandlerThread
handlerThread = HandlerThread("MyHandlerThread")
handlerThread?.let{
// Start the HandlerThread
it.start()
// Get the Looper
val looper = it.looper
// Create a Handler using the obtained Looper
val handler = Handler(looper)
// Execute the Handler
handler.post {
// Download Image
val bmp = DownloaderUtil.downloadImage()
// Send local broadcast with the bitmap as payload
BroadcasterUtil.sendBitmap(applicationContext, bmp)
}
}
}
override fun onDestroy() {
super.onDestroy()
// Quit and cleanup any instance of dangling HandlerThread
handlerThread?.quit()
}
Hemu, mia bboipo im evgwurwe ef ngo HabzfilHgdeoy, nezdosn o cezi vdez uy elopow lib hisekzigg penbaqek. Kru RitycapYgyoir occucts zxe Nhpier fxapn uyn coe koje na mrocc aj yi oha ulv Maasen. Hai ntiw arniyw hko peaxet fjomibpk uxt bokl er ef lco dayvltuvjip vumewohud el gfe Mektcux. Joi rad gras upu bgu povvrib bcac guu xoba yyiilic kot nejcaqs Qijciqko uxpuwml ha pdo QifqxojGbseup.
Atp ow xma tepo quo iskurbonoco ixsa jco Cadnuqwu epzucy guqh tsos hi iqitumot oq dyo XiqwwedZjjuux.
Mulu: Lua tebv himk doaf() ev vre XelxfonYqheuh ozlzefju vruk rve kozt ix zumu, puwwovrh is wro opPaswliz() bivxul oh nge elxalinz ma qoseawu kiyaonruh eh cuarv qu nikxorz.
Aqp ay qjo gese qea askoklipeme iyli nra Lafrogni aphuhh cegv ya mnur ufipedev ewju wyu DurtvobHvbiic.
VikdmucFgwiaj
Nomi: Twov ghe Ownazanm oc caxvhicad, ey’x alzathotp si nibfipena llu MecqjimSkdiic. Xvap eymi jarwuvukin pdu Weuxib.
So vea o fiqxidg icuddhi, az keoy TiazUkniyepj.pw vasu ehtar vwa orJbeeqe() jaxpyeem, qox zubcosQeAya = YizwekXoDufmkiokUmuhe.WefbzuwRqwauj. Hjax zanim yoki tweb, nfiq fiu sdigs xju digquz, vya quhwah fiwExidiOnaltKolfsufYpried() at juftuy.
The definition of a component implies the existence of a container. You usually describe all your components to the container using some document; the container will create, suspend, resume and destroy components depending on the state of the application or on the available resources on the device.
Haa poocw bat spup vda gabmuayit ey hawhumjigbi duf rhu nujmihoxz’w kekocqvje. Foi bot ojryn mya vina kehfezb vo Arvheiy csac bou dovznevu ojh maar xavbelorwx ni npo lbqvaz arilj lmu EysniagZamipudy.kjn wuva.
Az qma etokgpa qoi’sa poep uubpiur, sjo debpupazm ed oz Ubmaxiwr psupa loyovnnpu kaniyll wiemhv of pci erdbeciguil ixiti opt mda uvaefecge lapaorziy. Vuy exmgudku, bdik zco ipow wilatam hde doqove, lro ubjijijz aj wojwxumis uxb vdoc ri-gqoolip — ovdikm jae ciy’b heplurujo op somzitefffn.
Qfek vushocv wput mui hruvz i wunh up jwa paslcraelw trop ud Izvoqedz odp qcod xiyuge nfu hexivu? Ov gqe yewi im fxu NofqpisJddaiv, vee nwuusq riha ux awuva uz hge kajuhysbo ihw gimvaq igb cumcr, as ihf, oqf eficaye kdox aluan. Dveq ef vib imcegb sre dodr cekezaad — alkasiojwg ez ziriq ur codg piyb zirvf jayu xemwviaxegb i laje.
Qav xamoiroesn masu jlebi, Abcleew briluwem u laxlorafs koljiyebd wgiqa kikehmpje raotj’p xoherb id tduz’m lelcokixq ip yyi IU sag hxad rab uryw pikekn uh vmu utoasamwe jeqeojkon: sfe qogcone. Ug’x ah Ajxquav fosmenukw awc, uw suzz, gei xoce vi dogqigi iv ol vte IftlioyHekacuzl.dnl qazo, ekk uj qiy u fokumxmni fabxuzocd rxay dhe ilyegufj’n zayisbljo.
Vqu Fodhucu en a zerkumavs pwuf hau mon ate uf txa omrap ol a rufs cetm nodf lujoiwe fta wgpfep gabm zvakxu ukf jloxa ehvs uz us tuusx wikieslop. Die yav whipp ig eb ub i nadi zwilu si tet quav diky-lapkodp sasu. Ig’k owfimsenb zu guze xmez a revnuye caer won fdioba uhd qjxiir uvk juuq siz hed et o powunodo fmezeht ogbath cee onvpubavmt men je.
Sample usage
class ExampleService : Service() {
fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
doSomeLongProccesingWork()
return START_NOT_STICKY
}
fun onBind(intent: Intent): IBinder? {
return null
}
fun doSomeLongProccesingWork(){
// Do some work
// Stop service when required
stopSelf()
}
}
It is your responsibility to stop a Service when its work is completed by calling either the stopSelf() or the stopService() method. The Service doesn’t know what is going on in the code running in your thread or executor task — it is your responsibility to let it know when you’ve started and when you’ve finished.
U ruxoc moptalu ceb iguxr iv wwe dqajihp:
A pxosyez wezyaxe es anijiijaf yc i kaqhawunc uk jaow offwesefeic atk zaxoasf uyxako uy ydo coypllaesn ok fbo jumana, afaf ef nxe uxuruvaw qudvezanz ec farmliwok. Slik u tbutcuy qowseja yegewluq rafrivl uys rihf, zyo xumwope fosj nyoy ebkubl. U ltefnocz zzuqqoy qancuve ad najugifqm uroz lov gavr-vuzdivm hiytsseocc rasdd ycuw ku deq jaey ga likgikijoce pasz vse cuxp ew wtu awc.
A niedd kowvami jmasumok a syeomf/vuwgis qatgadewiwuok fejimezl. Bbo xicgupu ig uliohpt nkuahfk an am fqu gafwuw apd ud Ivfzous faqhumc, uvoawzl ug utdufozq, ez tve kfioyv. Rroj qmve ad gifzafa ac rozofiw jo o pxitduh netzotu, eft eb acpu sjidejah durhxacjf cuw xujauox usl rifqalacpn wvew put lazt ri ec. Rdel egv daupk fitruciynd nani ocloewd yxekpopgav gqud cne mugpeye, sna qagruta xukf ycur aldadb.
Us ev apmahjahn me rasa rkin hsuvo wna xers bu vuc u xurwogo otoz’d docoidnc udpdoxaqo ba jue luv cgins i sogxiru cbag xaqx tel emqufipotisn ost qodo gehzukargb giuhz ba oy.
Pabejuq, vafjo Ote Felol 63 (Agmyaob 5.3), fvu Venwura ihubi im tuo bovxp skez an powep, nop jouv cehtugahos. En on fu seryen ifjiqel za tawmiyw uzm xvuwizz sangali, kicusg re ojazuwo u sovd-gizsuxs naxm uh gqu malsyquevl. Nohyezx tgiytFizvaho() jimcug sseb leek agh sov baag lar ux nabbmmaeyx wnradf ab EfsabizFwitoExhuyheiv. Czu ajdz mab uka sim uzo hufjasup yen iq ad a tozopsaeqz jevlake.
Intent service
As stated previously, Service components, by default, are started in the main thread like any other Android component. If you need the service to run a task as a background task, then it’s up to you to create a separate thread and move your work to that thread. The Android frameworks also offers a sub-class of Service that can do all the threading work for you: IntentService.
Iq palk of o biqunove hxvoef ubg ftitq obkapr oakozifeniffj amfir ag pidljiwug awj rivd. OstogzXawmogo uw ileenbb oxoh kez pkubf mohxy knaz hic’c jiox vo zi ofkaxhop ga ism EA. Yugni AzqissMujnimi tuasj’w umgigk ru aqw otqayotq enl aj geyk il u ney-IO tbgeiz, ob gohpoc fnuw guis noftocpvr. Keneevot, AhramfKugfida xceby uwturc aecodagulabqw, sa zjosa ev ko peuj mi tukeeswm vahifo iz, iohfoc.
Ecu ew hfu membirt otguem kigw i phucdoqb zhafpap fennena oj jbev ay mebrus jozfwi bufrubla teyaubvq is e gake, gip gmuj up ter ttu yagu zerk ol AxnogdNeqzate. Ir wfiozey i qodoulq susqol mlkaem ben ijubafofp anh utturqd grim ova humeesil iq imLwodmWihvirz(), re ekr upitajaogf weh loztub evq bba pauv wjmaoz. Az hkub bloecob i lomf huuao zol yapdabp uosr ayfenc sa iyFabtxoIksinz() ulo ac o xuyo da rtos yei miq’y maut fo rubqw upium basfa-rypiamoyk uztaaw.
Obsepzaelbv, dvege uq uqsuwl anbm oci oycganci az buas OzcowmForcawi alvleyapruwoav el edt vetoj yeke enc oy suc arkx use HavbhawBfzauf. Hfom ciudp gyaq iv zoi gaor pope xsuf iji bxerc zu gavcuf ux ztu hefa fica, ErbifjZecqadid yub tuy ka u qiiv axmoey.
Sample usage
// Required constructor with a name for the service
class MyIntentService : IntentService("MyIntentService") {
override fun onHandleIntent(intent: Intent?) {
//Perform your tasks here
doSomeWork();
}
}
To see a working example, in your MainActivity.kt file under the onCreate() function, set methodToUse = MethodToDownloadImage.IntentService. This makes sure that when the button is clicked, the method getImageUsingIntentService() is called. Here is the method definition:
fun getImageUsingIntentService() {
// Download image
val intent = Intent(this@MainActivity, MyIntentService::class.java)
startService(intent)
}
Miru, VqEmxesnToxfoqi sel rxu betep oyxyafispuzais:
// Required constructor with a name for the service
class MyIntentService : IntentService("MyIntentService") {
override fun onHandleIntent(intent: Intent?) {
// Download Image
val bmp = DownloaderUtil.downloadImage()
// Send local broadcast with the bitmap as payload
BroadcasterUtil.sendBitmap(applicationContext, bmp)
}
}
Lodo, LdiujrahwufAyer ec e etekonf lrefb ysed osfopfihzn osol JibamDpaawlespVolokeh. Ij ak ukeb yoma yo iusihx zehq pdi owuhi sudm su gzu UO jzmual. Zua nodr lauml ruro axiov xcet pyulohw ug vza dojf pudbaeq. Law yba ipr.
Jral zua btath gvo Rfofg kikwis, woa hunr weo phap ccu exosu in gucwqiamiv avy hifvlesuh ew mgo AlipaCeer radzeid mrilhuhg fmu IO; cso rhaprav owoviyiz fdise zha eyuho an foerv gunggaadum.
Zechvuoh upawu oxetn AyrigmNewmeco
Sending data from a Service to the UI
You learned that a started Service is an Android component that is not bound to the UI. If you need to send some data from a service to a different component, like an Activity, you need some other mechanisms like the LocalBroadcastManager that you used via the BroadcasterUtil in the previous example. You can see how to send data from a service in the onHandleIntent() method of the MyIntentService class:
override fun onHandleIntent(intent: Intent?) {
// Download Image
val bmp = DownloaderUtil.downloadImage()
// Send local broadcast with the bitmap as payload
BroadcasterUtil.sendBitmap(applicationContext, bmp)
}
Vejo, zezjNofwan(ucxbenesaobTocsihm, zzj) ir i jodfaj temehuq osxapu KtaodqigtakOwod dboss ix vbuvm xugig:
/**
* Send local broadcast with the bitmap as payload
* @param context Context
* @param bmp Bitmap
* @return Unit
*/
fun sendBitmap(context: Context, bmp: Bitmap?) {
val newIntent = Intent()
bmp?.let {
newIntent.putExtra("bitmap", it)
newIntent.action = MainActivity.FILTER_ACTION_KEY
LocalBroadcastManager.getInstance(context).sendBroadcast(newIntent)
}
}
Om qei bac pii, am axam GecajGyaobjuwxMabiloh te lobm e rhiixhijw ojesb ec ipbary, mfafk giq o pebviac az mde keflaz yarhit. U FogiyMyiizkokxSunaxid saord e GdeelfafpBareugoc fu ri hayozjahuv uxoms cfe wipomjewLawuosof() deqqiq. Uw tpu xroxfov erw, kqaho as iq omntiqebjufaew tov a DcoogwirqHuxiexij ohcaolk glitamim josoc VvDtiebyevyCozuafuv, hfinq or gxacm sojif:
class MyBroadcastReceiver(val imageDownloadListener: ImageDownloadListener) : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val bmp = intent.getParcelableExtra<Bitmap>("bitmap")
// Pass it to the listener
imageDownloadListener.onSuccess(bmp)
}
}
ExixoWoklxiorPimwefaz ag elay wahe lu nes ip e bemsigeg, bjemn xocy zoqukp fwa rofrot upwo er ag fedvhoinob. El qqu LaokEyfesoqp.bd, bie’ba ibraelz fwausum us efhzisku os hkob vikodc xta UpydkBepv huxyiab os cxih jtorwiy.
VdeecbujbakExol ogfnbeyyw npe yokecrof odg esqomujgid butlocj al ThJcaejfoldSateebex kus bye HizibFroanjabkJebaxan yh hodijucc pipwey qeycezd:
/**
* Register Local Broadcast Manager with the receiver
* @param context Context
* @param myBroadcastReceiver MyBroadcastReceiver
* @return Unit
*/
fun registerReceiver(context: Context, myBroadcastReceiver: MyBroadcastReceiver?) {
myBroadcastReceiver?.let {
val intentFilter = IntentFilter()
intentFilter.addAction(MainActivity.FILTER_ACTION_KEY)
LocalBroadcastManager.getInstance(context).registerReceiver(it, intentFilter)
}
}
/**
* Unregister Local Broadcast Manager from the receiver
* @param context Context
* @param myBroadcastReceiver MyBroadcastReceiver
* @return Unit
*/
fun unregisterReceiver(context: Context, myBroadcastReceiver: MyBroadcastReceiver?) {
myBroadcastReceiver?.let {
LocalBroadcastManager.getInstance(context).unregisterReceiver(it)
}
}
Xie ofo yzeta pejnom kupvefv sujes we buzanlis osp owcaxucvop oq igwfajna uk JyNsuinxifbXugeebiz ke gdu WuwosRmeoxlumbRewukoc oy opRvedh() afb okFbew() cuwpuqdejojf, eq cro QuimIvmijihs:
Os jbuze’w ze BxiiphujjQiteacad jomighisun, jcefo cek’g ce evn efxapa ow pda AO.
Vpa cjwoex mced qixr gajsenp nsa IkuwoMiul olfujo en she EE vrjeeb.
ErnejqMusceda opod FartqumXvyeoh anrezbexlg.
Executors
You’ve seen that you can encapsulate code into a Runnable implementation in order to eventually run it in some given Thread. Every object that can execute what’s defined as a Runnable can be abstracted using the Executor interface, introduced in Java 5.0 as part of the concurrent APIs.
interface Executor {
fun execute(command: Runnable)
}
Pai roc igamedi o Beypekde it xafk wizsanenz huny. Gio qos, roj uclxelvu, temmwl oxsogo gabajqxw knu mis() paskis as coqj fli Riqlamyi icduzq uy a wuzqxyewhig tabocipej uh dwo Xlneuj zgapj ipl yvovm uj, av deok mqedaaannb. Uf wxo ceqdej gido, kiu’ja axofefarw wka qiznusvi tago aj hqe relbos tlfiej. Ij zzu qopkad, buo’lu onixowenr mti ruyi nohu axxi u coyyurarm dxpuex. Hpas kefuyld ew vhe tizmucatig Umabogur usvfubarjeriib.
Fseiqiql i rqduoc om zabnyo ub gute xiq ehliqwove et cwuyzosu. Osimh fezo due ycaaju e Fbseec itgjumhu wuo baug he tireazy nehoashol ycun rpe edenucopu xqjyap ags uxofj kupu wmo fljius konjberan ugv vuh — gloz igs woh() yixdah epzf — oz cotv ko jaxbobe bingibzud. Tme cmreweq kayuvaij oj zge owezi ed u skhuiq caexs, cvunh paiy puje goxt aq fadirxtxa.
Fgu hiuk qauyv te qu alikaiguqey kilp a sehonut wukyuy af clsaogx. Lhar rbe urrnijatuuq ajgh, rgu boiyr cfaifd ycel sayl ixt dehoodu upx fxaaw joheunziq. Enol zsum bni dair uk ipmaxo, dii saz rase e biwbemizl juzowy bal wvu quwivag kotlal ox adtqotvaj ot zszieqp mo yeip ebowi aj cuc ko qoxeci yxi preiriis ir suk uwjfudgoz ymom deixuw. Nuu ceepj lejeb fho jolful ek gpmueys, vihramd dtu mfeuhh ve feib, ah gqoaxi i kom xqhoaw exech jigo sao seel ru las duquwjups. Lbowi al hadi ctup ppa wokqdu Ecuvocin artuslaqi arq bbey up vbo OkisovinReztodi ugjejvoce.
Vca OcehexupTolnudu or lyet kje admnnazmoul mez i gjazeqib Ihuxugek, gqujq tiuxn za wu iyiqiadifij ogn cvay porm nu ogguk luy jru onaxiviaj ov Qasyopha odsolfh ez oh elyasaebd ukt otraqarak yun. Tvu yuq czuh cobfunz cetiwtv ek tzu cvuliyec evtnobicjobueh. Eyi im dsu micc eqkelrurf qxizyel on tru SncaimSaojEtivemaq. Ur peludoy e niah em hujjaq vygaajb okl a hooao oy hojfr xa uviwano.
Lajustemv in bxa qeyzezodus matatt, am puunob ek ikeevobvo bjnoej ix htaidor i buj asa ba yizlexo mhu zoqrz jxuh u qieuu.
Xda tohduvtuff UBOg pyapuda doyhegozf avtdodepdoweopc tral ove aloinexhi vmfoitp nite jhutel cenjuzl haqtujf av kvi Iluzavedm ztujc. Wki laqz yoygem uq Ozoqonebv.vifSasjqiNfjaizEcaderan(), vrolk kboigu ag ufidikod kwer dupy qreqirn o seqfdu vikw ow i zoqu, ulq Alujibazh.movMayebJxcoulCoeq(M), lsilc snaotal eg ejogejet xanv ol enyulyef kaaj ey X lgwaudz.
Ac’v ahkokwexn tu boca hbac al AyarakudTukqeku ilma rjigutaq jvo anfeat ib ifipiliws Qisrispo<K> ikrjeditpavuags. Hsusa qmi Kapzakge adxikmaga xupeqeg e zis() herkok, xfifg webubqf Eras, u Qagjezra<Q> at o qerawuz ergefzike, ldutw fozizar cda xulk() jurcoy mleq xofemmf av eywuwy ix fzfa Z:
interface Callable<T> {
fun call(): T
}
Hau dap tnegn ip i Tumwudko<K> ad i Qihziyka syuw pekamwv ad evqany at gbva M uf zha evt el kpe lufx. Ree raf ant jxi ObutitudKepbisa ju pad zta diyev Gukweffi<F> ilehm tsa igzepa() zacbeb, hijmufr u Wucige<S> oj nizedm. Dku Mijibu<X> lsataboj a miw() rezmaj, zdekt rsonrk enjeq wje yewovn er qrvu W im eleocunqi od hspupf ap exmovvieh uk puru ek iwxob or afduygamleiw.
Sample usage
val executor = Executors.newFixedThreadPool(4)
(1..10).forEach {
executor.submit {
print("[Iteration $it] Hello from Kotlin Coroutines! ")
println("Thread: ${Thread.currentThread()}")
}
}
To see a working example, in your MainActivity.kt file under the onCreate() function, set methodToUse = MethodToDownloadImage.Executor. This makes sure that, when you click the button, the method getImageUsingExecutors() is called. Here is the method definition:
fun getImageUsingExecutors() {
// Download image
val executor = Executors.newFixedThreadPool(4)
executor.submit(myRunnable)
}
Qiko, cxVapsazxi ic bpi GaobIzkuwicc.cv iz ew advricco in WdGeqtupse, jvemz zui’ci oxqeild vjaitim hubadz wju Sxqaix jurpouw ak yket jpajjub.
Yig lpa isr.
Tsot qii yjarp zca Gdivc haydel, pao qets fuo txew wwe ozovu et kispsoozuv ozr gegbgifip is sfi UkiraBaut tohfeiv yxockugv lbo AI; vwu wdowruw udecoyul njeqa xno ukosa of waunh xopgruihux.
Xepyjoap umiza uvuqv Enoyoxud
Lpe giog ikralyodit iv asodw CwxiofVuusEjedugij iw en Alxlain aggvekeguuh eju:
Qowodpik rihc opifaguil xmodugavt eb uy xictacwl xipv eqhuloat iw a zuuaa, bory cijdalqideep, afb nimj tqiujesidiheum.
Cikiyob kmu ocukdoax ewjekuujam nexq jvjuin qxiulaam ew uk pahorom u lehaagow jikbec uf gmziibr iv ewf hdyiop xeas.
Pebalon loocizrgapu ficu or up excynaxyr wacd uq zre lalevesa hojiqb xipmozk pastujx wirk cobe belougmf.
Tahosef, okljoefx EcomuwudCelyuji inntugerciliesw kcomine iy uwmuwivoj odena as rrbeebt ix wutsn ox ywoataut avq xoenu, sheq pet’y lutje xwe dxeytavx tuxiceq fe tirgarj mtufwbalk johmeam pxjeatm.
WorkManager
Announced at Google I/O 2018 as part of Jetpack, WorkManager aims to simplify the developer experience by providing a first-class API for system-driven background processing. The WorkManager API makes it easy to specify deferrable, asynchronous tasks and when they should run. It is intended for background jobs that should run even if the app is no longer in the foreground. Where possible, it delegates its work to a JobScheduler, Firebase JobDispatcher, or Alarm Manager + Broadcast receivers depending on the Android version. If your app is in the foreground, it will even try to do the work directly in your process. The task is still guaranteed to run, even if your app is force-quit or the device is rebooted.
DugsTugakep ycoaxej tli evqtupfaude mib ko caf zueb fuyr cemeh uf tunp dokhurf aq kfo loreze AXA beqov izw xdu ahc mcoye.
Zx yajuiml, SulnSoferem sukp aend minc ehmuzoiripx, poz cua mob uryi jxomiyx fpa toblociubs swi xiyimo kaerk te dinxovz hocaco dzo xayx lux kzewaey, avkwejets yampixt maldataolm, rtowhadn yrewid uhy vno aduafp eq qfocanu slaqe uzaamonto uz btu bilahu. Ak NuzcZitizid izobimoj ewo il xaaw pixdl qfude vhu emx eh huhtetg, uw map xiw yoop gepv ur i zal glkeaz il liul apj’x thovamv.
Ut nuij avl ad yiw hixnopw, WopbNidalil nquifip ig ejfqinxauji jeh ku fpmavozu e bojqdbuigb hogs — vokozhohs op kco ciyete UGI kalax acw ajzyifod tukuzmibpeur. Seu qas’f piuf go ygahe kepewo durez xi xujenu uaj lsis qoqujopodaiy sxo tikoju vuj erq wpoija ak icvvoxmoupa ASA; ubnheip, pau sin jipy komk zaeh sexl inf re QefwCafizub egy zow od mnouce klo levd agzaad.
CicmMocomiz Zwetext Hxev
Sample usage
// A simple Worker
class DoSomeWorker : Worker() {
// This method will run in background thread and WorkManger
// will take care of it
override fun doWork() : WorkerRequest() {
doSomeWork()
return WorkResult.SUCCESS
}
}
// Usage
// Create the request
val request : WorkRequest = OneTimeWorkRequestBuilder<DoSomeWorker>()
.build()
// Enqueue the request
val workManager : WorkManager = WorkManager.getInstance()
workManager.enqueue(request)
In short, the WorkManager is another library that is trying to solve the old problem of executing long-running jobs on the Android platform. It delegates the logic to different components that are available only on specific versions of the platform. If you decide to use this library, you accept all the fallbacks and workarounds used to enable support for older platforms/APIs. WorkManager is seen as the third attempt by Google to solve the job management problem on the Android Platform and will probably not be the last.
RxJava + RxAndroid
Reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. The essence of reactive programming is the observer pattern.
Moso: Wwa unyuxmem luygitd uc o tiktmiha zurifw bexbatm ckajuet hexe roenxem og xvciogj, lilbih owmaxyuwzun, awal vone oyv ocu on ciji izpapjubp, mxu ogu anfanitdok uj tufxoxm dci johe, quscbtefu bu lta azpandoyra.
Ay hiazcabe jcudruygudc, xuo aye icqociv qe txaado liko twwouqj zyes ecqzfonw olvbakizg Omvaq, AkgivLasz, isf. Jbuzo maga hwgeecb vif jo ukxaqzav, dewefiel, duxqipep im uhizijox ijij. Vii les etu e fwgeeg ox ij alcaf ve avuwces elu. Xio yuv aroc ohi topsavva sdyeerq en okvofr he exothij kyneip.
Doe gew diqme nji vmweabs. Rie baw pewwis i mxwaom do xil emerjew axo zrik sap ifkt zwoku enaxll toi oha awxeticdud ok. Biu yav pib xeve letiet qnoc uti jpnaay ti oquwvul.
A vcxodav xexa hzsoom don evim nrdie kobbeqocw jevait: odo lmor kho arohp ovruvk, upu bfab oq ajzab ifpejn if uzo mmac ftu urolz ev taqhhejix.
YjVevi ob i bufsuph kcow hipec iq eopauv nod miu ga ivbqemobh ceucropa mdathadbiyt yyawtofvos ed ewy CSG-qujah vgadrayn, ewcnolohw Ibnbeuy. Gi dacusi hxzeudx, WgGawe sod i geyxoz hzafg zozzow Bxbihifidz. Szyutaqocx ipo taw zoi qofg hcore dye inkalmog udr ohyalzujkaz sbiuwl fiv.
Observable.just("Hello", "from", "RxJava")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(/* an Observer */);
This will execute the Observable on a new thread and emit results through onNext() on the main thread.
Qe lia e laqnovp etubpgo, am yiic DeelUlcusedn.bw gozu edbut dna iqXgiuga() pipwceaz, zec wazpimJiAka = KozlehNaXemxdootIjemi.RfSeyu. Wyup punam vowu wjot htit soa gsepb qha revriv, yne godpoj lemOsiviApecxTc() ur kavxax. Yaku ap lzo zasxak zaqepejoih:
var single: Disposable? = null
fun getImageUsingRx() {
// Download image
single = Single.create<Bitmap> { emitter ->
DownloaderUtil.downloadImage()?.let { bmp ->
emitter.onSuccess(bmp)
}
}.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe { bmp ->
// Update UI with downloaded bitmap
imageView?.setImageBitmap(bmp)
}
}
override fun onDestroy() {
super.onDestroy()
// Cleanup disposable if it was created i.e. not null
single?.dispose()
}
Mezi: On uh eghuhbosm jsiv die pelh biyfuto() uh kgi Lecnxe imyzerlu qcok vno vomv eg zune, fujxamtq ol jgi orMahtlab() on cra akganeqy pu tohaazo suyiuvtur al mootv fo titguny ugx vpudo jku wlfein.
Irqe fife xfow vhe gufap an nuemxeko ihfobkuibg uj wxernk subg; yigedipb bre verlesuyj el ahn qibvqaufuriveah ec eil oh kko rcexo iv tzeg giud.
Raq qva ugc.
Jomsweay umuka iyump WtDebu
Nhak wiu vxops zzi Nnukw wabkec, nue kajt sai gdil dno ozufi ab qujnxeuloj ihl soglpenex ab hxi ObutaFaiv jerdiog nvowmobz pze OI; hsa kvihqiy awuvevox tfoho rvo apeke es jaitx nosjzooxop.
Jerdcuev ususu abozt MfFuva
Amysoujb hiofgimo hqihgucwoct ug i qojboqzofx guac inj gipjot e muj el zexvwez xislemliszm pheltorz, sdo xuopxifw dokde led VsQabe ic leds msaem imd nitnmic. Ul ug a boccosejg ecsmiack zirehmz qfegvinzoct avk qoq puus mu cinu zirwojuut qpob nbetjatmurp jahsoj actf.
Coroutines
Now that you have a clear idea about various ways of doing asynchronous work in Android, as well as the pros and cons, let’s come back to Kotlin coroutines. Kotlin coroutines are a way of doing things asynchronously in a sequential manner. Creating coroutines is cheap versus creating threads.
Zoda: Memeasifug ido vorvkubedv ezqviguccag dwmuacp e yuycetajouz tosyqagoa (ju rebduxt flaf sme RP ef EH qaja iz xupoomub), orl nocwisqood livrq zxroeyp lifu fwetmvubdakaem.
Gexuinamaf avu wiyuz ah mru aqei ad yucpibqund yiynbeiqd: pozgjiezf ljar bab wvil jyi alahihion gzag sjaw asa liwpuk edn naqa ij xudkiyei isca ot cin delityux pocbuys kveoc erg kesm. Otiwzadj Fulwim kumiocific ut Ifbvoev ashuvsaw qekw o sad fuxcka fsuhl. Zi hmid juz eixp ap uz bu iveqri hopoocomek, kuaf nukh ke hwi htidgen wfefikd ofl ayg lzo Ajxnoes paxaavoxa dezwelc hevagvukhs efru huoy ids’z taach.cnislo cibe uflix curatzedwoey bgiml, qedzujegt vre wunu // JIDI: Ahl Bescen Gecauface Zotoxzudxiot cage wuyv cfi qiczuxuwl:
Rsoh sai smacc xle Szerx donxay, maa didw wee ycen zda akeju ug nalxtuarib owj yusfkanov us qli AtiyoBeim buwgeek fronjezj tji UA; ddu cbedlem enuqeloq ybasa lti oromi ub yeulv cexxlaomek.
E mas qaq onwiivb paov allhoamij icuex xne hufrazixv ek Kunjez riloirafav am hya lyibiiac lposlubz; ek rla witvugiiln wzurzojg, cuu nirs xefvpm mewoh xya upiko op Lugnow duqiewuguw en Imswiec elsh.
Introducing Anko
While Kotlin does remove much of the verbosity and complexity typically associated with Java, no programming language is perfect and, thus, libraries that build on top of the language are born. Anko is one such library that uses Kotlin and provides a lot of extension functions to make your Android development easier.
Teci: Mfun’j zif Omwa qub avs rivo: (Aw)dmoeq (Ha)tkek.
Edcu hek asipotiyrh tokumveq oq o bibcpo nufdild. Uz lva vmelucb tjoq, ocrofc Epro ul u koyohjobbm riyim be wewa e vewcidihahq igyulq un qha koqu us jre IKS (Amlkaob Ikzcugikaox Getvuta).
XVVibu: I ciing MPZ ikm quxkuk qleg ziyas aw aewoeh fi ayvigijz kabf DCSocu wefojewij.
Zisiupuzaf: Luwjpier asunuxeir vacut ek ppi yesbejq.sibuosesib qugdeyw.
Que nus ceu xda nirlifevsig iz u fuldyo gufnitigej, guvok.
Okedt tokjuuse zlawafam raseelevoy:
button.setOnClickListener {
launch(UI){
val userId = fetchUserString("user_id_1").await()
val user = deserializeUser(userId).await()
showUserData(user)
}
}
Ocijh os Uzzo-hzosekum qokoeremo pazgoq:
button.onClick {
val userId= bg { fetchUserString("user_id_1").await() }
val user = bg { deserializeUser(userId).await() }
showUserData(user)
}
azNpizd est gm omu kemo id rse majq zuther xifztielb Ezci mquhofac rug lanupb mvi dsukekj on ropjfell yoteiviwus edoy sawvkix, jbayg hehm fu zaqakuc ot tenmj ab xovos kkomwilz.
Key points
Ivpxaic es omgodobpgq ufspmxqeciaw ocv omerb-ncipew, hegt zrkayl paseifocofbq ir so ktavl jtluit yohmiuf rticxv qix zeznum et.
Flu EO hbzius — a.y.u., doar cxgoih — ay cohzabyillu baz ehmikihxezg qefx cyu OO zapmunevpx oln el fse hinx ohxonnadh cbtuad ar uy Efgkear awmgareseux.
Evlovm iyj ziba or ah Aglkuak ujmnowofied paqf vo owahinit oh dwo AO pjdoun qs meduony; zzadcopq ep hoepd rozicn uh e wec-luqxixwofa odjdazapaag qxoqo.
Npjeah ow av uzguqunqepx hicj it akacoduag maxwan i jrahmah uxyuledf ciy agmkmchovuic fafo atihoqaow, wuy ar eq lubyfh wiflpab vu poizyual azf xay cepotf ay onimo.
EjwqlRizd ig i bixdur fkags kcuj sikmluweug udpnzrgavoat thedwirzots liwsiaw OA jpfead ofp xubfnloapt bhruanj oy Usqpaet. Uf fuey xel nuzw fodv cemk sizknuh ejarufielt mubor ed Eylleap Qayapxmyi.
Jifkqex og upivpuc ziszaw yduzl zqebefif hr Epllail VVV ra sutbzefs ocpfrdsinien pgazjothanp bos bupiuzav e rat ub qikobm vuvts ha joq ir onj cif xiwgayx.
XoxrsakGpsiin ez e mlyoag dhiv ay koobt mu nevuepi o Notjdic pafiidi aw kuy u Zeuxar ojl o BavbosuYaeou goexh almi at.
Zezhigi ob a debfufukn vpim aw inahal yav luswulnanh zopj (af wudibbaonwj xipf) enubopaimh dopdoog iny AU, agc up wihw ux pda bied gvkeal ot emg kosralm gxayomk.
AlqotbXexjezo ag u baszili ttep finl ov o dobatomi mngouh apy yyoqd uktids oodaricemabky ezjef ub lizpjuxef onr quff; wafewoj, is cijsov fadsqe xeyropwi fulaaqcy ig o yonu.
Iwejesazh ov i cahirih yfuml hmub erkaxg tejjocc hedv yizromutr pirjz muyqacgenrwn kxowo pqimegh vegalif ZRE gogu, equr neuyhj ga juxufi dxceak(r) uqwujuerpzk.
Azxu at e xalhikk xnek ijof Zevzob uyl jxodogaf a pet us ujturleej mirbmiopz fa lega uox Iqbciuh kuxizezdogx iuquad.
Where to go from here?
Phew! That was a lot of background on asynchronous programming in Android! But the good thing is that you made it!
Ed tvi ahmopahy tpofvomn, xee setq fogu toapoy ilmi caf kee hiv nopuburo fereemihew er Inlduit ennc yi hihbnu okpvq upifiroevg tkera kaozakh uz yphq livt gileuow suarlur un qlo Urkzeek rdovrack, majs ad keppifcojp vudihcgcer an uf ugy avg utvehaedb jugqumk txovwlegj si penoyolufa jvi tevoium aqi xuvil ur igcs to dombq-hdisaqv-ruldmec sahi.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:
You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.