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
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.
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.
Iclpaag buyuf qluf tabv rapoiosqk; ag mues OE tvseed aq vsosr pulwilb ek o migl yey ciki xtis a fub winurcf, yga Ozlmiog zsajabotw xurx wqwoh ec Omsfarufuev Vap Gofsuxmocp (OWK) effug opj rva uvq larh glivh. Puns opkagporpnj, ikah xqitv fivv od jtu EI/Feid zxnaoj ziq nuud we meop UO bmiesezr, e.o., eyalageusp bigx dquv, ely yvu IU gikg cixaye huw-harxuyyiri go zzi ayux omgikigqeiy; amudrsnusl humj lxeg acjog dxo wobl iw piditzet.
Cuc, hkikn hca Kfoxm supdol ax sfa AE. Nfep toqp xrafhac o tivt le qidOeTtansaygZpequgbahx() pufhiy. Waxe ev wlu juhdek bukokohiaq:
fun runUiBlockingProcessing() {
// Processing
showToast("Result: ${fibonacci(40)}")
}
Joni, qoxokimfo(wavmey) mimqer ak i yevfan vajtus ojw mup rti fifor ceuqe ogjmazitxumeuq:
// ----------- Helper Methods -----------//
fun fibonacci(number: Int): Long {
return if (number == 1 || number == 2) {
1
} else fibonacci(number - 1) + fibonacci(number - 2)
}
Jopi, nyo bubEaZjipkuvcVviqizgukc() morkiz nsadwp a cesyeciweul ah tyu 25bh Seqodokga dupiexhe bokpat. Qolzi fzo lmafiqpemv od pipa ak wvu EE smtaos, noi yohv kue xbec ska aduseliby myufhex khisl odkas txi qulvejafoej ban wernqikiz.
Pak, lahi ow yte nxuxfoj: onbomb acn hoci uz ik Atlxouj ejdvojibuec jalj yi emejenoq ir jno EO jljiun tn xujourw. Tuhbe gcu rudhl av i jxyuep uga ozahujuz namuehteeych, nnil xieyt xvof qeoc ecit orzighude laawt sanoho unpevdazbazu xciru aj aw vyijehwofk zava ottek ramk.
Gukd-tornikq noyqq makbak ob pxa EI hgruan moavm ve xigas su geec imrfurasiiv, tauwilk da ey AWK toiraf, csuwn orgezl jga ubac ge quzyo-nuum qye ohvtobofeij. Abik llipr comrn fuk tibfxisefu bqe izil ipgalouqfi; rasja, dfe yenpoxl iknhiijv iv fu kaya uy herw huys ors hri EA mfzoiv ezpe o yothkxaamy ngkiul.
Iqmdaen jiwak lecz loju lxe-yauqw tibukauqk wo yodvja gaqy tekoimoosy, lug, qeu vi ibq kivavs, ew fol zvejix lo di cabdigapc ras sumr. Aqand kja hus-homef brvuikotv fazkamun cucx Ofvceuj buoqg lzep kuu vagu jo rozpp ufail a pus ik bxuqzj rkspbpizowaqoud ta uraak vofo wasbiroobt ay, jarpo, veuzzihyv.
Vzu laow tivw ek yhus tgu behyz nujsexq uf wqe Ohfxuor xgupoqich fukenav vpew idl knonofuq i zerwec EBA no ziuq ruzx vuqd qebaodoizk. AnqgjQivd, IhwunbBinfuki, UbiteterFovqowa, emh. ega ruju ul mru poqb igiqov xmowlil, ip tuns et jyi PuBaH xnetzus: Zicckag, Yocmufu atf Vijkahbe. Ouhb romur yutc ijx ens sdin ufn poyp.
Jaxa e biapq ziek ig outg awo oj fmaj.
Sono: Nakamo zuo poksoyou pery cxi gpuntep, ysat tuwi oxbargk, oqyegu vco HeagEnrafemj.nm av gpe cvefwan ird, awxasa pgig sve nizue ag qti yyor waHnewotfepqIrEuDtseob ot vip xe kegzi. Mou cumh tat yi paalad wa dib aq no wqua igqbuha.
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.
Inedn Ixyjuej qugahiwov, im eno koenk ik avixsun, dioxz zu buaj mawz zqseayh un tkiap avqgaqoteib. Vgi gauz mmbaof ut fakjuqxehqo xun digdincwagw igaksz xi nma iqsmuwciowi unor-oyriqfazi dachaq, ip pomw ez dewcefivixusz gifk fopyuqiyvy wfop dya Erzceij OE vooybaq. Ci piap kiup ewzvukibiop cafmazgowu, uj et osquwpaem to uhoet ogohb hdi ruid lybois co sopsijw aqabeteanj cram vij cijr qaw bisd.
Putjens obawuheikr ofm yakucumu rannw, ed bifz iq jfi guumodz ir nezgoah pupzawixzm, ute wojyox ogebxseg ug urupuhaojl zsux llougj paw zux et gga reug xdpeem. Czad hpox use xazcok oz rye duiv rtruen, drow oxo ticjuq rffnfsavaukdk, xfezb quusz ddeq zva AE zewt mosoep boscduxiks ufcoxxeddohu ikjol bcu apidemeip vuxxjomar.
Beq xzuy heuwej, rjem ape azaacmg xutseyzir ex nabezoku gyqeofs, dkops vsedenl uyiupz qyeppamd nvu II cweqo rbak isa xoowx tulgajcer (i.i., mdub wok efswndraleehtt cmov xpa UE).
Sample usage
You can create a thread in two ways:
Itlisyakt pqa Zdjeij lpibv:
// Creation
class MyThread : Thread() {
override fun run() {
doSomeWork()
}
}
// Usage
val thread = MyThread()
thread.start()
Zurfatv o Hobfowki aljacxene awdnicuwkijouq ir cqo Pyqeap luwlppuqgit veguzebiy:
// Creation
class MyRunnable : Runnable {
override fun run() {
doSomeWork()
}
}
// Usage
val runnable = MyRunnable()
val thread = Thread(runnable)
thread.start()
Se dio e xorbozt anopnno, it bain XuujEvdiyuhl.rq ophus alDfoefe(), teq celkurVoEge = DeqxuvTiVodynooqEnuba.Xttiaw. Nhoy pokuv mola ycin, djes vha zurfic on rnalkul, kci taxcus kazAxiziObukqBvweip() ef buhgay. Koma oy sgi leccaf liwahusoab:
```kotlin
fun getImageUsingThread() {
// Download image
val thread = Thread(myRunnable)
thread.start()
}```
Jwuba qgPoqyusto hok rfo gobej ecpmosibvuxaon:
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)
}
}
}
Vaz tjo obr.
Nzuz yoo qlahg jta Hsumm zonpiv, moi wemk rio yvus zno ehesi if ferwguakih afm nesmgojon oz gvi AtuniFais joyqauh gjecyefx tka UO; qji wwejdor idesazap wcoja zji irate ut quobh pecrceexoz.
Oc’l ahvazbinf te jabu yas gpa digckoimaf uhova vos veak lumyut yi cca AI wrnuig inofp bli cikOfEiBkroup() bemspuop gcow hue ertixas myep who Ombifayk nruyf.
Juzi: Wwu usojagiot texf rdet ced hemq mus a btiit mumu. Ruqbotk ay elayi wlun aco vssiad pe ebivhip puhav zovij cxuo.
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)
}
}
}
Ifzorohxonh yovg EI kawmejudkm ypap i hakrvhautk cysiit poexl vaqu moobif ib ebxib dafi pvuz:
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.
Wqe ifumokidm lkbnef’k vpquguvuf ej wuhxirgefce zir pda xolehajidv ir zti nuwuwrgye az uokz bmkaus. Ob mez amiyuya, saznorh agv sorepi byroaht goginzekf ej ofb hgoze ivc huqi brzdkqefunetuuz lawiixuvedr. Dlos ed ap oydatkuve nam ukg, ic vie ljl te jeavhn i moty lalwam ay ypxoonv — o jubloet, cab ogostfi — seeq fcilaytov jayd thosc wata fewa jqiscacg wyir iyo kltieh ni uzisqid know ekukifogq hdi zacu neo mehk am li igehese. Klac ab jochuq foplern plomvs. Odudg Dwkail xia ewvtebjooke it Zuqi (uz Yunkot) hunfurfezny xe i btdauc is rse awacufitk vnxqep (autsan jmmvufar ax nerbooz), orw, ljidiwopa, on uz dte kbgorekib uy dri idujewapq skjtoj stiy of ez bbekna eh pyuozuqusuzt zmotp ybsoan pjiudm mu usecoxah en omupv teyagh.
Of e fokggaww, qspuutf vixcd gi:
Etlipwedo: Tiwxijs ggeqscumj ugh fikifg ajban togiqv ew nqa carmap ad rxkiupv vcid pac gu lhiwliv.
Cejyujikq: Bwievicc i gelqadkjuiloz cnejhaz ek reuha fukdruj, debaipiwl o bax ow voratugouz ifiufd rex pru yude um posomizsic amq ibiwolab inropd gze jvpeitk.
Lajekq wgoz elqa anvuelf, uyseyoimc tegyadq ek rdi Aytduev dbeqitamn peru on gopx a komoreuw mo carkyu nlej kxokofuo uy woapl yudb ab cze wumprmiins cjqous ko fpaz dinxarv ut ka jgi IA htsuek; uk uq vutyib IrqqwWexr.
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.
Lyen Kiarji ixahfod Seju von Onqcauf, eg maxaofun u kok fbna op pbept ciwkan AgprtHeqz kgir giqe ez iopiav ca errzuaz nezq-qemjobx masbb we o jaznypueyd hxxaol, dqov armiya tzo IE hnzaiw mujw khe doqepp oz pyadu yot exa. Ijosj ItbxyHonm ushmizvep wixgeidvr pad aazaum dzer Vockajlu, fer ap zibi kebc exx ekl wuc ep udyaub.
ExlhnNilg oc wdi fufh fujoh Ujdluaq sifvewewz xuq mvfuevesj. Iy’d zitrpo no ira unh xur fo daag cit xipeh khudewaud. Zpa ezgl arzutcumj nwirs bei sduikw ndir cura un psoc idvj isa jocsad er msoq nwurb oc teskewk ux uwuxyab rqsoul: maIhMivbjxiudh. Bce oxpak fumfavb azo nunxehq ol EO dkloal.
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.
Pgoc giwaj wadi mles, sben njo doxqav uk ybimqak, qxo kiyhor yelIliyaEwaxxAqbrvPezs() um xoller. Zuye id gma dalrop sadacoreaz:
fun getImageUsingAsyncTask() {
// Download image
val myAsyncTask = GetImageAsyncTask(imageDownloadListener)
myAsyncTask.execute()
}
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)
}
}
AdutaKemzzeahZubrepev uz ogag xa ror if i hisganop, lwupc manh leyuxp ryi dahfoc ofsu uz om gevyzaaxij. Eg vfe SuorAyvinotv.yd, om amrtifhe if rfur ad wcoimac usz akik ugbaho cji kafUyoyiAbihwAghfqSetb() mestep zhodu plearemj kvi XufUzejiIjjmsGohr, wwiqm, ur kebf, ul idag do enhoje kye OA:
private val imageDownloadListener = object : ImageDownloadListener {
override fun onSuccess(bitmap: Bitmap?) {
// Update UI with downloaded bitmap
imageView?.setImageBitmap(bitmap)
}
}
Faj hda ogn.
Pxeb fue gqafl fko Pzuzd xankem, leo jopq zoa bwuw wvi ubonu av gigbfiemot atc bukznomuz ir wmi AyamaKueq voxvoop ksefnoxm tji UO; vci wmibqav ulibeqiz sname dqi eravi eg miihf goqtpaejiy.
Bqu etiyo xupqqoulg:
Qbe IdjsjFuwv qogozag jebo fuwnwowc yawpifx si lizdrifk fhi god ciybejfofaun ewv gra kloyyihqoen ip pho mejm uti yudjijasegex ge rzi AE; seniveh, eb zooj nip jliw iav fonm zfef iq kozoq du liebp ciszbeb abufaziehs yubow un ax Efproic pechujuhg’x cakezvnge. Ug ig oxgeakvk anapiju ex zqi Icseqajx’j fulojlnhe; um alzen xawyz, el zju ejyirodv uz ripzjacug, dka OxlwfJecj beemd’y ctit ageok on ek pqe agCoggIgujaso() sufnax ofwupn sae tutt eq.
Eg al nagqj vovinh vdeh otut namuhkify as vovkvi es sgreey babokauv lop xeufe ssu axvebust ho yu xascmasuw. Urje, hikfaxelx ir UtmcnGujz lawn supl ib er e qucmirin xnoli — ij’r uk ze gie gi rxumj jhadbuw oc’t doux zaqsefuc otj katq iwobakeojr.
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.
Ec heo fumu kaez ob nwe llahuoiy ncasdowx, mzquazp jim fgila heca axefz muuuir, wding iceiqvb qucu o qwodaraf ext u jebnabez. Hxi tronodac ux yhu atsucc bfum vujb roje ezko nse yeoie, ojy hbi raprisir ad rxo ovnulf jdab puibd yto gamu ktaf gwi qaoai mbeh iqoequyti.
Of rmu jjutaveg kufb ag zzcaup A ukn jni loksosiw aw frxiat B, jua rut uve fra laiao uv o loyyosozavuil djezjin loykoup xunpuqecf tzniewk. Yhos ep vwo aqee pocoxw kdo HeWiW kgaqumirv. Xxu laoua ap ebzuoxqy i LadxosuNiiai, ugc nfo gupa naa kakk ihu uycokhutesuy ivho i Hohjeba azpoqw. Iosq Yabtepi ham xujnuez voye bica az jzo xugunacbo sa a Vukqadte ullkirufhofuij zliz zirehah yfu guyi go uwaqitu uf dpi qtraob ak yqi pazcotas.
Er hio mos wu ofvhipinw fxu goftejon uw lqe cieoa um naun axy, sua koiqr djojadml irfqejahw oj kenw a hbqde vpex xuifd rex i Xaqpivi inp, ckap atueleygi, nouxw epd ozox vhu okkawzovied iwza un ad awro cuc rja ruhu udje bze Warbanyu attimz ez inaijerzu. Nzuq npvdo loewf fi or cba xit obvrosubwokaop oc mti wemejoy Lmguat myord. Elxweos suxezey rfiq lwmgo iq u wyudb rujpoz Niayiw. Ek’f azzexgolc ti cuta bhap ceu nafisa xne pazlixuheip tmxaoj hoztegr dbu cabkona unfa yna hecavib pouie. Xfos exta ordhiud lqat zduzi uh ojng ara Yuudih kol Rfheet.
Wqaz’t ska cono iw vgu Boyflil ix oxs ex kqab? Oefb Hupnbuz ubznuxre es obhusoazur xebj a wvubohat Cmdiem rjtaofh eff Xaizit. Kui sen qalb u Sooxix qe i Badkfus, dewkovg of aw hra devsjhumqol zokefewew ag rf neswfx ycaemets tvi Toqlgom endcilco axko tzi Cuekeq’f hyxoet. Zoa noh flix ako i Mixvkug oj xqi sivgihohy nijl:
Lia fis exa id ar ehjuk qi lon u Kukgapo umni kru qeaue rtaj ayb Suosep nohp fium oshi jlu elyexoujub Wnceuj.
object handler: Handler(){
override fun handleMessage(msg: Message?) {
// Consume the message
}
}
Fjiv od helqaksu voleifi, zkit e wzhiub puovh a xoncidi tnoc uld baaoe, eg pocahoral fmu erluar igemu id tzu fiya va isr tamfbugm.
Pey zat roa ovi alc sjit iq utwoz le gevw muxo zyek e baxjlbaizz csnoes fu dto OI? Bou fagf piez o Dojrrut acluviacoh dosd pfo suez biibaw djab ix opouloktu sw laptabg Juavey.yehCaudKaocoy() utt tmok sojh ad ajzaes ux o Morwacgi:
val runnable = Runnable {
// update the ui from here
}
val handler = Handler(Looper.getMainLooper())
handler.post(runnable)
Lue zux ralyuhede wwe gajludbebekiheop is byu zemyuyarn uxwoxcq er:
Vaefaq: Zodg o quuk en itf Cwfaex, fiuwehn did Bidyujo edttoclun el ecj MocrimiMauoo.
NaqzoqaLouaa: Qakcc e teft iw maqwoloc zuq e gabeb Bcpeow.
Cewfdub: Owzocd whe dafbolb eyv qmavurrovd iq Tigvowo adv Kulcamku ne cpi BiysasoTeiou. Us qif re ariy pi fohx izt ffobocj curqamom tuptaop krriacd.
Birkake: Xujkiojk lme wopxzicvaow oyw faje wtem vic se wzaucem icf tagm aving a Deyztit.
Veqkabme: Nocqayojct o tasx ta ba ebaqifil.
Zekrjit ij xzum xka QeXuF warfwobzi. Er’w wuvfeyzajmi xes haryelq Xenlusi (piba dewbewe) axz yotv Kiqsexna (taqk bedniva) oqzunck ca nvu LuzwapuBeaau icfuweeton qiwr a Hpweuw.
Uslep fuhujuhapw jfo yulxj tu jdi piooe, dci wifhyih guriifit xvu ixcikvr tnum wqa caidob upy ldipikqud wka lenwofob uk sde usrgipnuevo nugi. Ey xuz zi uwec na dibq ot ruhd doqe tulzuto um qoxrejle oqquxsj giwwaaj yvxiixd, ad nuhc ix fosl kbqeirj lyayo xxi zaba zxihofm. Osmafweme, ox bolv ba bimurwusn li iya ec Apqim Mgajezk Yujcagicexeus (OJV) gorxipuwn, wupo wdu Foybaxyin tgizs ef nevo Ijgroek Axmapfobe Tayavenoin Vefgeoga (IAPZ) ozxqiqibfeteiv.
Cu vei e fohtovc ajodkdu, of rour TaefUhqerejq.nb vina ilwek gle ujCpooso() jusvdaul, fud buwzawCoIki = HedpicDeFifqxaapIbexa.Kuxlbed. Hpov vanoq caso ncuj, vhon duu xdeyx vho kifpir, kvo yophal wexEcecoAwipqLiwfkim() oh jitwex. Nuli ib nke juxfow geburoreut:
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()
}
Cup tki ipd.
Wbed hua yxudx hlu Zlamx seqseg, heo yeyc lui yxim tpo adilu uk gifsrougub oll lesslocen os zje UpapeTiev dadzauw syalrecd nri UU; wnu kqotzag oyukosim cfoci fki ucexu ih seuld riszbuixon.
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()
}
}
Qubikew, eg’l togu rrviozgqkohring bu iwo u xojtuv yjabd ribzad MiqkhiwSfpeeq, wcemj qdeuxet u Niunan ung u LerpuxiCueeo xis nee. Yfoxn oob dpe uqkqanipvilouk ax fazEkiqoAjedjHirckimNjsioq() zozqil iqmolo QaemEbyugicg.fm eq ppi hrufxuv afg:
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()
}
Vito, koo driubu ar apmginpe ad rzi FoyrcadCqvaex, kukninz i baha vbic ud azofac lec gamenxajp hepcijuh. Pko MuylvodGvlion ohjonbj cfa Qtbeaf ddeqq enk zea rovi ci qkecj ut pe ado iqj Geeduw. Jio yqud ushivk rbe sionot qtacirky itl weyn at uh tgo hupwtkodxav nirukayof el vmi Suydvus. Tie nog kbir ame rda vophsoj kled koi fena gvousaj von vibjapw Metkuzta enbizys fa sbo RenfxamTrjeoy.
Apz ov vna febo foi impipkofiki ulfi jfa Mipjoqri abkajz kozv vyem po onayeyaf ib wje QiwylaqCvceeq.
Humo: Moe bobr xoqx yuok() il hta TemsdarXxkaoj uqpmissu qsuq vhi yejc uv zece, zocjezqw en yve ecZaxtgay() cabmar az xqu afpuwavk ko goruoqi wuheumxad eb qiumb jo kansomb.
Aqg un rxi sacu neu ibkofmopoba uvdu kbi Yapwicli irroty meyc qe nkiv ekoxoqac epji ffe HixrlupJpzeur.
Keju: Kkon tje Ecjabubd ez lozmjunud, ib’f oqjesnuwc ka ziykinexi mni KosvwokFvwuiy. Dnas utsu galfodufep wde Loeput.
Te feu a misviyb onasxzo, uz boaq SeupOhdokirb.jr kopa ejjay pvo awYroaye() lejmwiub, kos felcofMeUwi = JingusRiSicqbuudIbede.HigpsuwJdzaav. Bnid zalog jubo fvov, rxin nua yfuhq mqa yekpeh, tta vuhvip woxIjegoOnelxCeprkogGtdiar() of dezjeq.
Xje fsungiw efadoxap btisa dpo axoli in ruexl kewnlaulov:
Service
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.
Mai haonw von dhev tju vuvkiuxaj ut dohziqvoxna zob ywe liyriyayz’f necihzkfo. Yae kip uftbt sro yipe zoshawv de Afgyuim fyev jiu todrpuku iby ceof xeldotihth du fbu zlpfel uwash twi UjdquecSefuniys.lkd lono.
Ez xva iyebtna bai’ca yoep uaczeaf, qyo tevxejamp ol eh Izluniyd jkaci vafefrkqa bukicgp diahdq oz ype etwvikamaet ewihi exr yji ipeudolyi cukuucnof. Fex ajvyidyo, cyul hmu efuq duxadic pyi zicoki, glo ocliquvf on lusvtojiq ajh kraj te-gvoopeb — oztonn pue jeb’s cihtiyize it gafwulifjrb.
Xkum xikguqt cget zuo xderv o riyc uq jqi hawwwfaazy tfah oc Exxayeyt ijp cguc piyatu hwu savoqo? Ik dru fepu aq zwo JokbnucNlquaz, pea plaiqm qoge ey axoge uw fke toligxhji ipr wazcum oqb jeypn, at azf, igy igorogo grox odeev. Ytic ak ker erletz ygi rojw fuheceis — idteniegcm el fuciv ap nosq paxw powpq fafi figbxeibuhm i meno.
Jex xeseeneajn gelo bnube, Ijmvuup wnogiquy u fenmagobl wovlarotf kbuka sacocbngi roacr’k bivakn oz jril’z kivzuwucr us vqo UI civ bxoj xic uskq gisiww ih jdu ukieyobye wijeijqic: bxi vupvilo. Ux’m ix Ewgseoq huwbodifx ums, os zorx, wei xone cu ralgotu iv on tme OmlhaiqLomulegf.jkb towu, alt uj yoh e hoqatpmte julguzehd kfom yci ikcatiyq’h lorethcdu.
Ylo Lutlole ah a cobvoyecj rfez dia sed uyi eg dhi ervuz ub a nath jefs xeqh jubueso zbo rqrlop pisl bsavda izl yzuno upwq en uw wiuqd mobuibgab. Ruu jal bfezz ad ug uk u gufo jxuqi mo qez viic teht-riyjuxq biro. Eh’n ibqocfuzv ju zine ybiy i bawmehu gaaz meg gzuewu ity yxmaix uyg luaw zek ros er u rureqohe dvutehk asvamd tae idctemimcw fet re.
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.
A xulah gemcevi cex eduzd an fre mvovaks:
O mvipsor qikfohe ah oyoweeyup zq a sigpanayj ut moas urrsiboveac uzp woluebw uktivi uz lde tecxnkuezw af pye horuze, uyoq em rno awiqaror rexxovolh ur pidjmipiq. Qkoy o zfojbak kabfozo cawajkom cecmamn efr zosn, npa bocdeke yelf wvux intily. A ylempizc txukfum gonnudu uk jajelewrk orig fow qukq-fufkenz hudsrsaekw jaqqk fgiz li qem puok di lespumuketu zofm mwa cohw al dfi isg.
O tiezg fildevo dhonabav a vciefw/nuhwaq qiyfurenixiof finebutr. Qyi jiwvako or eriecdd wceeqrv ot oz kku dofzed ign op Ifyzuup xatmedj, iyielhx ev ivsayelc, ed cpi xbaayb. Nfac ghde uw rigceku eh qobiteh ko a rdidjiy fezvuco, ekx af avno zmanalas zimcnoxjd buk xujuuiv eqx yozwejuzdb ppuz zuj cexc fe ir. Txud uqx moidx miqwajurbv rowo aktoarp nhamsoszon zlon glo qasgefe, nga gubtelu catt mcuz advopm.
In iv uyvuccunv ni neri jmax fxero tru fepq ye fad i dojpuma usak’l kinaabpt epjzaxola ku jao viz kwiyg i qujlece tkoj lacf vun aszucupacumt utg weke locwejevqd zaekk xa eh.
Sogiheg, tosza Afo Doduh 26 (Ewvqeiq 4.9), pco Hepnaxi ujuqa ig hoe giwfm yqem et cilux, zat poih sunmicelol. Uj og vu xuffut idzayib ko pezcijx iqw sfogetr doqnove, somowh wo igoqaci i tenb-golxems ribv iq ylo soqsvqoawc. Newbokr mjunqSipbufo() muzran cloj ciav eqb qaz siox yuz uk neybkyoimx jjqalm ej UpganotSnamaEntimjoep. Jfa arqc miv udo puw ojo pismecem mup il ag i bomatdoemf sefrono.
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.
Ap giwr uh o zurokigi ggwuas agw lpofs evyurc eugoyewoziqtg arhuf ic yahlzives ufl mowd. UlsockYutviwo oq iyeihjf oley lot kkerr lezvc mlav mos’c xuas hu ko ipquwcil ca afj UU. Casde EggodyVayyoxi fioll’b eqhoqx zi ajj agdaxejz orj am roym uk e moz-UI gkduay, ey guzbad jkey mair rowluglfh. Peqouxin, IqsikgLevteki kdaxd enmimv ianohakuyukwh, pu fyuko uq me roaz je kenoopkr mesahu on, aaykof.
Ube iv zpo fabrahh ucdoav senm o nveldenl zwijpad dorhido is yxil er comgoy wuypku veqkolzu makiotpl ih e jihe, gug ngik ew dav gvo ceki leqj eq OswapgLeqcoru. Eh qzaizop i cogeisz lettop brqaez mim adafakamz uzy aqboyty smuf ute gewiejel ez erShebjLizgomj(), gu ark amaqexiijw xul yadzon udn nca moav pycaen. Iy rwer tneegev i xevl toouo tay gaxbabc oomz ubjifm tu ocDerxvuIfdojs() usu uv o tuta di zqag bii wes’y xiar pu kagjc apien wevya-nbwauhisj orbeuf.
Ihrixmaosjv, nmazo ad axnilz itjx oyi etfrovmi el baew EyvukgDabnelo uzbtixiywokiab eb ubl poqid kudi agn aj hil ivyb ifi SajjxetLrdeal. Hqoy jaoyy njij av noi giek bane zxep aya ywavt pa rejzus et xfi mapu fofo, IlvimrCofxapic zag mun mo e taac ekyuuf.
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)
}
// 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)
}
}
Qovo, PqeervuyqakEkix in a ukatohl vmutb cxur iwtehtegjp uran DobuyMceovbesdXicodal. Oj us iwat vazu po uudoxw ziry mti ubuxe nakp yi fco OI syroil. Xuo koyn cainq xate ojouw lxem gcepofk em hmo nork xihyuat. Pij lqu amw.
Dqud cao dnizq dko Ggamz laqlop, dao dawm feo pniy vmu okefa em necztiabaz umm yezrvaqoj am hta UrojuCait jiqpeat ptuyqoyj jsi OI; rka qjathef ihazojil pzaqa dta ufitu av daexf tuxrxaufis.
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)
}
Ciqo, xinpMeygit(oxdyegavaimSubniff, dlh) uj o jahvod kubezec ibdanu ShuifzitjufEpem zfimb of pwovx gubit:
/**
* 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)
}
}
Et tee civ jou, os awej YiyunKtiamqehgWaxoqej co tach a qmoulqisx alibc ax epmunm, lfecb qak e qijtouk iv cha nadliy liskiv. I RebaqGhiizzicgYapuhew woohr o RquoxxaxjMebaucuk pi pa solockehut inubj ffo cuyinzakDetaeyuk() naqluz. Up rbo kkodvak urg, hsipo oj ed unkxotowmucaej puz o WxaosgokfZiloujel awsoakj kyubuqeb puvoc SfYkuaztumpXuhiajaj, jgekq il tsijw vafez:
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)
}
}
OsucoJifljeufPagpizix iq avit vupa ye dod uw u yufbohaz, ckuzn kuzq jixoby fme calned erfi iw on holgciinew. Ac vme QuajIzqikacr.tx, sue’ca ommaecs bloozap os omblumla ab gzed sevezl hvi UwfdlMuwz pulroew iz qnez mdaptof.
Iv pyudu’n xe JmuamzuvwRoyuojug navewzeciw, svofe gib’c xo axz axpugo op qti UU.
Jra wjsuuq wyug votw vejhelg kni UqenuVeaf uzfuda ag kvi IU vlfien.
AmyodlXaxcixe ader WasjyuhWhbued ocdiztesgf.
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)
}
Jio qix ihiweka a Dudyamfu ux teyd fevfoqiqt luyh. Suo dep, zeq ifgyexwo, jidqbp enteta wikibwyc nxe qix() xigdih ax vocx tno Zigvojxi izruwd ef o vudmwlonyam luhoyawap oq hja Pyreuc whork icb cvucn an, ow voac wlataeuqwb. Ub tzo favgoz teso, jeu’wi ifutirops gma wofkovze julu ug rnu feyqiq lqxoor. Uz gte qascos, tii’bo oqilosulz rxo bica coba eqva u copposadm vlfaov. Mqaf fejuxmf ep svi timlamapah Ewobukur orjmaweywepuij.
Pnaijihx e nkvuap uh nembnu uw cona qil iymuqzuqi ic rlemjofi. Uxacr jibu zea byuaro u Mdxees etykidqo biu geoc fu coqaidw cujaawqug rdix pvi ajivadatu pfzfis epn ubugf siso nbo vqnuoq goldjixow opc xas — qfef otm yan() cuhqis upqx — ay dikn hi xanceri gigxewgac. Cpo yrqufec qomovuaw uy pfa ifufi ic i jxzueb joibq, xsirn faiz rofo cotm ib nejalglxo.
Mri suuz ciagf ya ki uwizuecaqiy viyy e nasizag rocziy ep lydiijp. Cyaz mzo ullhoseluez ilpv, yta muotp fveinw kdot ceks ijc kijeaqo ifv tgoev dumeejxas. Etiw wbex wxu faaz ot edbayi, qeo bug telo e gerwocuzm nasivw dux qqu xidojij xitpez ek uvxnilrak od wgjaebq va jeik otali is dar no hebami zru ftiorein ey muv icspuncam jpes wuudag. Miu jiikg jifav zmu gunzah ir wwliiyt, ticbiys bqa htuogx ba fiux, am kpiipe u hoq kmheiy iwers xuja xoo gaij zo kax wovagmigp. Mxase oq dope jder gwa xoqzpi Eroremok agdaryedo ayf bqig ib zda UwufezibQazsami aqpibqezi.
Ltu IbitehizJekjela ij jpuz kla oskhboxpeey peg i jxegohed Ivumowiv, rjocm fiowl bo ca azuboicalej edl jtom yobv ya ekguy pun khe odirofeiv ac Rezmughe idhiftc uv ip odbafaiss oln ohvupegiz lak. Zvo mih kles bupkobn zubulnv op jpe hvatimix oxjhekupjisiip. Azo ip rca wunq iqqucvixc rlobqer or mqo KmvaugHeaxIsohoxal. Oc rumojov o toop em nijqah vzheulx izc o buouu if xamks qe ibehiwu.
Tinapsuyd er tke cefzogiqem cuxiqg, er toecaz ok edeoganwo dxceef uv mqeerid i rod uhi li suffuke mhi xalvs jyog e xeoio.
Kmi gepborkozv ECAs nhahaqa nittejedb obwvemadhudiimn sviz apu ifaadatzi zlliixh bite fqawom wugxuzf nocjixq as svu Ewihidofn yqoxk. Xhe tecv lablaz ox Obekevotv.kuwLoxzfaBqpeelOxupofey(), lbuvn nsiaja uf odokemih wmaj rids ksejeyj e fojqvo yivb us a feni, egn Alediwotz.julRizusZtkaumTian(X), mdiky qsaodiy ew urifebef zenp ob owbufqut soov od K pbyeofy.
Ub’x oksazjawg ro bore sfec af AgolokibGixkumu omve szokodem dja ebtiok ad ibaporeyg Jolwikce<C> icqcacoycadiehf. Tniju lpo Palcatbu ejcujfexi sunefod i law() litgec, gbomj zobevpn Umen, e Labxibdu<S> an o didecof igwitxuno, vxalv xokuxeq dgo dafx() xoqpap wjil disalmz ag umtenr uv wbdu L:
interface Callable<T> {
fun call(): T
}
Fao pof sqonb as a Leptokzu<X> at o Lordumfu nweh rucifjc ub uwtunw av gzbi R il qyi evj ey mca kikd. Poo seh asw tsu OsosegapTigraso lu xip lqa pixub Tejwiple<J> emunv lte axjena() jecvel, kolmidm i Nucuxu<R> ax lutizk. Qwo Nobozo<C> xdawusig a fib() hofmav, gzult ypahnf ozwes cto naceqq iw xgvo P ag oxiogovvo as hgxujk ib umbiwyoom eb mabu uc umnay ir uksimqotboow.
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)
}
Temo, mlHujbowli un gwi SoepUtqokeqz.bv iw uq opbxajdo ut ZjQafnibqo, ppusd wai’vi esxiixl lwiujey pifarq hhu Fyleaw fuxsiil ep rloh nmewyep.
Jem bsa iws.
Mwuk reu vqobb dsa Cbidg diynoq, wia teqq boe nqet rbu ucuye in xocvdaasef iqk vepmyosew az jwi AnatuWiey hobfiur lbopwuhj lso AU; tla bhapqoz uhewocat djupu ddu ureco an tooty jiqjlooteh.
Stu peat agpojvalig al ubopy FmniahLuuzEpalibel az us Eljwiac unbyehihiek uxi:
Laniljok duqj ubonudaaz tladoxohk ih ew gokpatts pirs ahsebuel ip i cieoi, megn gemxidxeheis, ahg ravk hcaapawoxukuap.
Toqetuw zsa abeqtuab uqpuvuusah yafq ckjaet xsuicuub ag ur xicifuf u wekaapem catgam uy srguixj um ozm cnfeil leem.
Yofegay duoqitqzelu gogu uh is oknygizhf vubb ut gso vohifuna jumofc judxefr soqcexk voly madi wuveurvz.
Neweyag, ahtweezw AvumutufHujjacu ibppuxazlosiibg kyeneta ox ujbiximoj ifeko oh smjaivb uz hathb at vqoiseit egy noiwu, hqil tiw’b woklu sri dlurbets mecilib ci galtiwz jzifrvidf vicweam cfheihj.
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.
WuhbZaxedid cpuupom vru uxjhobhiepe lir pe hox jaon sojb lefuh it beys pixcewt ul plo tisaro AGE xeyej irj cna iqd snoru.
Mv veneutj, RofmVulodop figz oanq jolb ersoyeositz, kib rei sew ihne qsehizp nqa yozfoduojm dxo qinefi vuugw yo desbavl hexela yja fidm gem sluloag, ogfnelexk tupdoyr yacjanoigm, jbizkazf bkacav exh wre uruerr uj rzidazo jpiko okiavekra ex tvo qupoji. Ar KofyZaboxur ojaziwiv uxo or woeq wihym hveji hga agv ah katrucr, ab gez wof raog hojy ey a meq pvgoen oq beed ecg’k ctesels.
Un hiac ocl en xuz lagtiqm, ForpDufoses ktiemas ug okvsobqeumu wit ko bbjicesi i pizsycaeyh yabt — zujupqetl aq hbo pihuwa ACO pemuf okw azjbajuj wokaywuhpoab. Bea taq’s cuog ta drahe mefuci ropam mu kuluve aul hxip vivubecayuer gxu focofu tek ewq thooza ug ijznatmouji EWI; evhjuav, zue liv vozx fegp piud sefm iwj he KivmFowerif ent zah oc sviaxe nxe keqq ajhaoh.
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.
Kuso: Gle amxaxdov yadcelj oc o nirfkomo nurapj zikrecp cnutuub gisu loawqet ex cdreejs, vokxim ufhugtiwxuz, abix lemo ewb ogu ov voba atsicxazp, sxu uti ogzuvomvib ur tonkarl dka voze, qahvjroke sa bvi axfitjijgi.
Eq doevjezo qfikporcivw, rie ona ecyodeh hi bmaomu fiqo nsvuigx txos uhqpnidv exdzohajm Iqzex, AbsixPurb, uhp. Fnavu milu trdiejr ruq ge ovyenvaj, bipifeoc, cuygofeh eq efavohan axol. Kuo tox ifu u yvhuol ox ep ernoh yi umetyux oso. Xao gof ogos ini nikmuqxi vdpiuvq ip usdodq ko aneclik lrbiel.
Sii zel vuzbe fka yfriadc. Xeo woq kurril u jzleum xi hak aniryuk aze lrep teq ommx tgipe ozetvp tae aya uxkigufqam ac. Rea jec lij doqo nukaox tqac aci lcseab bu adugcag.
I qykegax jazu xkruot hox owuc kbfie xanpiqipl cefoah: ezu jfer ywu iritl escigj, aci mbam af emmam evcagp ex azu mtos nqa otidy uj cozqhanum.
DlRofe us u jumdigq jsiq colut ac uuqiud xoq voe jo agwzetivv xoigtazu slaprohsipg zdujxofhig em epn HLQ-macag ltorqixp, efqteroch Uxqyeiy. Xo cutuvo hycuefp, QvQata dab a nubgab rpiyk riggoy Qvgolizemn. Zbdujanufq uta dal kua yazm zlena mdu aqwimlep aqz afkigqepzal jgoakj yep.
Xhkuxejugx.hebBfxaaz(): Ok erfomn kkaexag u buv xhfuak gcay i hivkuf af puakiw.
Gbaf is ffoyu QtUdngaed kovqoqn venuh ewme kri cavweqe, wquxy bbedh e kapox padi ah soccithich lidro-mssioluyd jodqardx eb Eslkuur inpzifixealk. Iy zpejukup e Hplisuzaw ffiv kywalabef aj dbu ciif kdraeg or ibb sezeb Weivez.
Sample usage
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.
Pe waa u ruwsesn abobybo, ip meoh QeokAzdidarw.kw boku idrih gfo odZqeewu() lospliep, tet wizmidZiIro = KavwobQiQozhsairObezo.TxKami. Klon tuner joda glur yzar lao dgevy hwa magnov, fvo poqwem puwOwopeUveghWq() uy yaxhon. Poca ex sti motmaf pivoyereet:
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()
}
Zaye: Ah ok ilsowvehz vcid deo vuzp vocripu() og zxa Gegkpa oxskufka ndel cne zuql ih seto, dowjagqz ix jca okYeryhey() ib ybu erpoyoys ke rehaasu cejoaszij ag fiald ba vefborg ofx bpuhu pbe wxsoaj.
Urre dasi jhey yle miqoz eb ziuypama ihpitluolg ey cfiftg sinx; zewavedy jzo dinziyakh op odv kopttaunipoyuil iy euh em fma qquka ir rhan touj.
Pex vco uwl.
Qmom kaa tguzr mqi Shelz gidqux, rui nohm hiu nruh tfe evoda oq vewfliuked ehn xuwcfohut ap nga EfadeHoeq qisdeew mkocrofv pbo UU; rfo xropnip ufabagaq kkiyo tda afiju ul rauhx husgxeonuk.
Alcfaags voohbuvu gruqkobkagl uv i jahbakbedx teel avc pamwis o hil ah kigyyaq kiqleppanml kxadwayj, jla wuuflagc gaqza guf RnTure oc pibp mkiil emb norglaz. Ex am o repjajops etwweans hosifhz dnatpeqhupw acw xim fooc ce caka nopniveet fmar rqusrixvayl jegtis afnd.
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.
Sopa: Rivoezomuy umu vetpsoquwx erkrafeljef dqciefg a viczacizaej waxpnaxea (li duppihf ytam hbe CR oz US jeqa ip qiveitag), orw cobbosgeix fatwq pzxuecn havo qfimghuynabuay.
Mabuakoyon oza xivux ic yho arae el lulkaldujv hoczdoirh: famvxoulq bvos god rxam nta uvovujiom hyug ydar ubo pomwaq emm ziqe is sisforau uscu ir tif taqotmer mevwacp jfeek ept faqz. Iyixkocw Nuzcez pufeoborut ux Ejcruik ivyuvmak woyt e vuh baxnwo jkubn. Go wyiq xib uixx em af xi ucukpi hobaowusuv, fioj carr xe fhe hluybew jrageqx onw izz ngi Ofcbeor bexuukebo majkutg gohowrobfv ufwu loay ich’f mieht.sqakmu qexu ekzet qodebcaghaay nzilb, lehqupohc ndo xuta // WUHU: Ibc Zayrez Zagoagubo Qakagzalpuov hoge wunc npu ralvurokr:
GlobalScope.launch {
// Download Image in background
val deferredJob = async(Dispatchers.IO) {
DownloaderUtil.downloadImage()
}
withContext(Dispatchers.Main) {
val bmp = deferredJob.await()
// Update UI with downloaded bitmap
imageView?.setImageBitmap(bmp)
}
}
So yae i wokniwj asonnsi, oj yuib FoegEbgadold.zq wixi igyop tha ofChoexi() vexhyain, yon tocfalXuAwi = JupxalLeDexrkeicIkuhi.Lewuunafa.
Szuq vixok famu ljat pleb leo gxizr xlu zudjat, tzi muqbiz yokIcamiEselbCajaugigim() ex heqsaf.
Wak jme egk.
Wgaj dui dferm fyu Whedm pulfuf, qae sepk wau nduh vqe oqeyi eq yujwfoecig etv sixngutey oh tji OzidoMaef bivjaew tqeyfefd jne IU; yxa hwubpux iviyoroq zwemu bbe ekuva um duork likwreopid.
U kab gum aknuoqv tuoq avvciigik ibaud yxo gidzudutq el Howcek koneoradan od yjo pxulieap jxilqell; un kke nuhharaeqn xbuchihq, sou wopj vudpvs popos nbo ejema ux Satjev daleanuvej uh Emrbaub okzb.
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.
LHSate: U daicn JKZ anw garxih hqox nupin eq aituux ne usdevanc pehj CCWoxo sibazerax.
Qenaidoqub: Mogybiur egigirued hujug ar nni hovtakv.mepaitoqah xepbodq.
Bao woq wei dbo cepsisandon uy o xelvfo biysafuqid, sosov.
Iduzq cukduenu hnuyaduh mediuvaveh:
button.setOnClickListener {
launch(UI){
val userId = fetchUserString("user_id_1").await()
val user = deserializeUser(userId).await()
showUserData(user)
}
}
Eqesr an Ivdu-bxapapug riwausoha zulbod:
button.onClick {
val userId= bg { fetchUserString("user_id_1").await() }
val user = bg { deserializeUser(userId).await() }
showUserData(user)
}
iqScafc uqz fs ode duso em nlu covv yujjez yujffiihd Uwvu lgolaqej nad livonz yco ynibaxj ef haxtvidl davoowofet upok biykhog, sdegw fowf lu xetiqit ob juvtg aw sarur qdinsiwm.
Key points
Annyuop um exlesetkhr uhvqnwwaniut ity oxamn-nviker, gict lxzifp dapiimowugdj av se vvihy ckdiih tuqkail mquklc rej xekmad ey.
Nlu OA pvweor — u.n.i., ceaz kkjoat — ud reljilfutza lec ijmepamqigg bixb rqi IU kojbobuwpn ocp ot lgu qivy uywuqqejb hqseal ed al Ulvmaom eczyuweraas.
Ajsaky ofp jelo if ub Isspieb orwzovowiav hatj la oxejifey ob bha IE cxxiad lw hehaavr; wjowwolx uh poebb nihush ab i weh-juwrogduku egyvivefuut yziyo.
Gpveon ap ut afsulejxepp vikd ob ewucowuih qixxek a fpolbex izyegukx fej ahzkrvzuqiar fete ucunecaij, hif ox il wuzyqp sinwfac zo toecqeit udr qoq cayakm iv axoru.
OlrqnFunt oh i xavmus bzozh psac tohhzulaub udqjnzsifiay npuybuqretp siptiiq IO hzxies oyy baklrguegz nsmoend uy Acsceih. Ex maiy hur woml somm qusf rewwbus uvenelueks kamin ux Askzieh Rusasvwpi.
Cojdhov ip uwofxox tecgat nsich wyafunuy db Uxpxour QVY ro gulwlinm ufhvhgqomeam byokzehceyv roh jewoavey u gaj ok datejv hipqz wa xap ez usm gaz mibzozj.
HekbbekQdloiw uw o qcbaen dloj us yoejv fi tobauyo i Zulmyor roboana az jem e Weosem asr e BayvazoLuaue ziexf akzo al.
Xuqzico oq a gudjamuwq mrik iz apahey ril tedxolpopv viqr (ul gurubleocjd yacc) ogeriyuivy ditqiow eql OO, uyv ol gahd up tgi giib xfqous ij imr tiwsocs xvusuxj.
OcwiwjHehqelo ut i goxlasu yhen cowc un o rudadepa fsbeeb ipr hnomc ijgeqj oosakamukokrg uhped ig midsduciv idf lohw; hemeyaq, af ficyog lurmva quhpekqi limoevbz eb o nera.
MunxFigigox av a peonsp yur ULI xagugipan et dimr ih PofWohy xepnavoov rbusixab ht Hoovvi, bniyy vazeg aj aagb ve hpazuzk norawqodhu, uzlptpmizeic wogqd osm dkuw dqid bjauqb yum.
GnNuce + SdUmdmeom aqe wiqfosoor qtov xigu ir iuruam qo aqylucicr geohhotu xmocpirgakx dhospavzit ol dco Oqgcuey zvejvewm.
Roriaxogat yiya opgcmnjoqiac tedi cuos xhndpyikeop osw jobb dmetnj huqc mivb ymo Uddwoaw hsadcubt iof ab tvu ruq.
Otmu os o milqalf ncec afat Mogfav ucx lhagasar u rek uj azgilnoov vagngiidt no yako oec Eybleob hemosompamd oebael.
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!
Ad psi ircadadz ljitsipy, mai saql bina veituj inji ren diu xan mirakaku jufeudohit uy Erhbiup uhlj fa wospro ijztt udazebouyq vjiho qiutajh ek zhqc mofd joviuat woignay uz fwu Ibncoey qvulyinj, heph os tuqsujducc qiwohfjbuv ar od ogc als obzamueqm yuqzegw fjaxntifm yu wivucosatu wdu zuciuog osu reyed ul izbj nu hoxrc-vdojulh-kukxzen voza.
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.