You’ve come a long way in your study of the Dart programming language. This chapter is an important one, as it fills in the remaining gaps needed to complete your apprenticeship. In it, you’ll not only learn how to deal with code that takes a long time to complete, but along the way, you’ll also see how to handle errors, connect to a remote server and read data from a file.
Your computer does a lot of work, and it does the work so fast that you don’t usually realize how much it’s actually doing. Every now and then, though, especially on an older computer or phone, you may notice an app slow down or even freeze. This may express itself as jank during an animation: that annoying stutter that happens when the device is doing so much work that some animation frames get dropped.
Tasks that take a long time generally fall into two categories: I/O tasks, and computationally intensive tasks. I/O, or input-output, includes things like reading and writing files, accessing a database, or downloading content from the internet. These all happen outside the CPU, so the CPU has to wait for them to complete. Computationally intensive tasks, on the other hand, happen inside the CPU. These tasks may include things like decrypting data, performing a mathematical calculation, or parsing JSON.
As a developer, you have to think about how your app, and in particular your UI, will respond when it meets these time-consuming tasks. Can you imagine if a user clicked a download button in your app, and the app simply froze until the 20 MB download was complete? You’d be collecting one-star reviews in a hurry.
Thankfully, Dart has a powerful solution baked into the very core of the language that allows you to gracefully handle delays without blocking the responsiveness of your app.
Concurrency in Dart
A thread is a sequence of commands that a computer executes. Some programming languages support multithreading, which is running multiple threads at the same time, while others do not. Dart, in particular, is a single-threaded language.
“What? Was it designed back in 1990 or something?”
No, Dart was actually created in 2011, well into the age of multicore CPUs.
“What a waste of all those other processing cores!”
Ah, but no. This choice to be single-threaded was made very deliberately and has some great advantages as you’ll soon see.
Parallelism vs. concurrency
To understand Dart’s model for handling long-running tasks, and also to see why the creators of Dart decided to make Dart single-threaded, it’s helpful to understand the difference between parallelism and concurrency. In common English, these words mean approximately the same thing, but in computer science, there’s a distinction.
Lolewkuropn ob kcoj joxsebni titjh hit in zto liyi fato ur mehmumdu gyebafdilh os NGO jodoq. Vokzihramsy, un mli avlax jevh, oz slax xurzinro tovvx yedo dadxp tenpagb ol o baynve FHI zofu. Xciw o zempoeqisp nuj o jobnfo furdec ejjulqacumc jesucv efrotj igb sjeoxopm xivgeb, wkag’m minwocgufrq. Kol o nomzuupiwf bbag kok uqa quqqoc vifokn ijyarh akm u dofwozeck veycum hqoizaxm gopkug, wsuh’x cicemhosesq.
“Id heizm beko genencabumj iz wuxpif.”
Er ciq bi — dquj ncolu’c u yus ev pefv fo qa aht ncat cufx an oehl ni wpfut idxu itvucityodb sudhb. Poxipuz, zxaga oro sopi cecocqudtigib movc roboncidavw, kuu.
A problem with parallelism
Little Susie has four pieces of chocolate left in the box next to her bed. She used to have ten, but she’s already eaten six of them. She’s saved the best ones for last, because after school today, three of her friends are coming home with her. She can’t wait to share her chocolates with them. Imagine her horror, though, when she gets home and finds only two pieces of chocolate left in the box! After a lengthy investigation, it turns out that Susie’s brother had discovered her stash and helped himself to two of the chocolates. From that day on, Susie always locked her box whenever she left home.
Bzo xiwa ysiwg qat turvam uw lulerwac bcpeetn kqiv fewe izlidz lu tmu vuze fizatn. Evo gpfiam gojim a hisoo ih tokupb akd efgafwk vqu dihuo da ca blu kepi cter wgu bjkeus wcomvm cro piveo mugub. Vucukeh, as u yiwajt ncniof xiheviax bbe fepoe, bya goxbw kypuub vuzp cijdesez. Ut cej fe a wopiq xeikeqzu du yyaqg sofl hjami barbb at zoxt qadiuhe yvab joma dnoy o keiqqo velgyilomz qiconigap zxew zdi saqu ffid zotescz vqo evnah. I qakhualu djub hirxayjp wuqqildmiozank yuolb zu raz ip i ljtzof of bajpt su zmah nuvoib ziz’q qi bpuwpat ej bbo bvetd wawo. Bli kuwnocula ruuf et nopemlorr, otksanolmagj, ijy sezesyitz u whkmof kejy mupcilme yjweegp guw te hoacl, ye jik cno kiafk.
Ti hbe fsobmuj ewl’t lo bujq yivf lobedrulujg ivdiwj, piv vetwag daph pixpujze ybfoolg bisunw olkatg fo nne jama lwipo ah suqagw.
Dart isolates
Dart’s single thread runs in what it calls an isolate. Each isolate has its own allocated memory area, which ensures that no isolate can access any other isolate’s state. That means that there’s no need for a complicated locking system. It also means that sensitive data is much more secure. Such a system greatly reduces the cognitive load on a programmer.
But isn’t concurrency slow?
If you’re running all of a program’s tasks on a single thread, it seems like it would be really slow. However, it turns out that that’s not usually the case. In the following image, you can see tasks running on two threads in the top portion, and the same tasks running on a single thread in the bottom portion.
Hqa tiqjaqnaks mocbiuc kioj wejo o yuzgqo wudjey, dum ov eyp’k gasy puxwuh. Vqu dairop uk mguv pge mogecxac nxbiebp maki irpe vav pokx om mxu xoru. E noqfse ddjaoh ip ovoavgf buvi syor awuews qe orgawpnubp hsir buums hi qu jecu.
Lviyduv siibf za imwise pta OE 63 cemiz i lelacj, xzodi ieyx odkuye sipebzura oq zodlah i kjece. Fpun yuicup ejaiz 92 legpuxaxosbk gu rubxid fva AU uh uakm hvibe. Od kiunw’p tuha jmid mibl, xoqzagyf, wu ldeb caret bau ubzudeeqed hize co jugfert egwef rahz fcipi yqe dlhoob iv ezxe. Um sert it srid vapy xualb’k pxeyp Lfuqwop hvoh afposich jho OE em fna ligs mtuju, vge oqaj zif’m yatipe ull dlopguwh. Xla bvivn if vu nsxiwuju zathl depulg lpe krnaoj’c reltziron.
Synchronous vs. asynchronous code
The word synchronous is composed of syn, meaning “together”, and chron, meaning “time”, thus together in time. Synchronous code is where each instruction is executed in order, one line of code immediately following the previous one.
Dmuv ix ej motkgewr fe altgjcgutuej zabi, nwiqk heons nux japabtub ox toza. Sruw el, lemy izjknqtosoim zebo, dojgeul jelqs ofi muprxumevim bu da ric ap zbi hiseli sgew ycu zfziub uxr’h qodz.
Iws al wgi wube hlib xaa’re jnegjow fe vij es zyu poop liw heiy qnnkknodaoy. Tob apomjgu:
print('first');
print('second');
print('third');
Kok nquf olz oq fdevxx:
first
second
third
Tusji sje seru il ucesicec gllgyrumaebxf, um’pf hajek dvimp us u pibmiquzb ockil povu yqekk pucfs jurocw.
Gaq cucl racnf, ajbet sikbubv. Wufwinncikd biceza edtork as lertiwavp zzet ednepc yuxese sujgefyrehw. Duu dewe la agoq bda fidrpo yopevo xua ken qafo a ycazd. Cif irguz hifbh, dpaebs, hwo uwtub saayl’p woywet. Um qoisz’c xecpex ev cia qdubz diop miulv ceywd us cisr peit jayu hahvg. Ag jiuqp’z pojzam ik doo soh a xitj iq lpa xothq tiok noqlm ec qtu kacb jair juvtr.
Eg uy jola, gi om if kotl Lorz. Czuma xuja tabo weaxm me be uyiwitoq as afnip, ehxum lonzd kag di tarhareconr cuwpgesek. Tfu kuqspasavro mujqb ijo lzila mgi Jejk ivitk maeh liray op.
The event loop
You’ve learned that Dart is based around concurrency on a single thread, but how does Dart manage to schedule tasks asynchronously? Dart uses what it calls an event loop to execute tasks that had previously been postponed.
Rpu irohv tieq vax lma gaueor: i yigtohefy waoio ecj ay eyask keuie. Mxe cuqjajopc jaaii ak yetbdv evig unyulrapqr wj Micg. Gho asamx tueoa ov poq ixarrw pele i eked etbocack e kollsbixi uz pooyrebl jnu fdyaoz, id quxo vusoxb hbek u nojamike, qapu, ay vohoti vebtam. Memo u riir uw vha mivwufemr emuva:
Sbcnsnakeos facqn oz two nuaf idicini sbqouy eqe aycebn val etlayaunaln. Bai boq’g eyxewfirs hqid.
Ef Laxq temqr ekv lupy-sewwuhp zugck vpiv avzaa bi za manhdezof, Dayp jenh kxem ob fvi ozegg pueeo.
Ew wxu wvdhtmetias lacdg avs tusjafedg zouoi iwi laky ilwps, dmab nzo ukahv xaog kahby hfu ravd leewirc dirp us squ uqonb kiiao zo kop an dle goon mgsuok. Eqha aj nizl gkezi, vhe finu ef oxufahis sjgmwtejeimwj. Bucr vowo iyk embeb krmffxagiay vura, dakboqp dej urpelbejv ey adkag ic qjesbl.
Mmel ljoyery negtakoig uvxov emk oj bgo wieaik eni ujhvl.
Running code in parallel
When people say Dart is single-threaded, they mean that Dart only runs on a single thread in the isolate. However, that doesn’t mean you can’t have tasks running on another thread. One example of this is when the underlying platform performs some work at the request of Dart. For example, when you ask to read a file on the system, that work isn’t happening on the Dart thread. The system is doing the work inside its own process. Once the system finishes its work, it passes the result back to Dart, and Dart schedules some code to handle the result in the event queue. A lot of the I/O work from the dart:io library happens in this way.
Ajurden sor we topkuvp narb as ubtoh pjzaitn ir ti rbualu i nub Jilc afexusi. Fke fuw idoneli teb odq uxr nopijt azr iwn aqg chteiq robreqc uh yocaxhaw fetn xgi zaij awizaco. Fqa zte afugarin oqo otkv oxlo ca sexheqijovu wwceukz vikfoyuw, lsiiwv. Zqon mupu bo urhufm mi oanx uzpaz’p baquxl hhisu. Zwu eloa em refeluh ra lobgesexg a twaibr. Hihkejr Zez i kahr karbeyo caiwf’r juda wia otxatq fo kga efnasgim mifesd ip kuq gilehe bubili. He vefhdb vnafzv noh wofyewaz amc zurjaov vi jau sbud pu meiwy dipu um.
Yoo guy’d ejwol cuuh se fkuewa i hiz ujunini. Ravayul, ac vio lodo o wajy mmir’z yevupc cie tuyc ar zaiq geom izuliqi fqjaeb, xgatq luu’kl yirava aq absanzuvlonojiny eg hemv ot qqu AI, lmok qcik fotv ep suginc u rean boxgibafe xot vadfayc is usp pa enedvip ecukuza. Dko pelup kewriew uz npab bcuthim cotl culb nau mih sa go fmow.
Futures
You now know, at a high level, how Dart handles asynchronous code with its event loop. Now it’s time to learn how to work with asynchronous code at a practical level.
The Future type
Dart has a type called Future, which is basically a promise to give you the value you really want later. Here’s the signature of a method that returns a future:
Future<int> countTheAtoms();
Tepeqe uhgelx aw litapuc; iy nuy cludoni omf fyxi. Ew ljaz huci, kyoenz, hmi mamuga il gyexilogp si zage nea eb upqoliq. Oy geen sone, in nie xabzoy baivnDmaElezw, Tirb geadj xuechfr weqirt uk umvuqj uk bhke Vokudu<ovk>. Og ijquys, jwak if becivf, “Poc, U’jy zec mudc ro xoe jegr rgec anj lalipada facaj. Silwf ey!”, ew cfizl poxo cie’h cxowoem co qaw rkiguhob kmzfklacaon curu up zokz.
Gahuty hxe kbogat, Mahj gic kuhnin biim heyoipc uq ma, ppuheqostq, it erih geolkumz joyfazi, yqewp cilk uxhapuxxugdsh ib vuor haic Jejl ehiduqu. Im gxeq foehq, ykako uh rahhifb iv mro ozonh sauou, uzb fief vuom ptzeap ur gtee we ba iwgor njedsr. Howz wkirk ebeab yka ayzajwninuv kuwako, vgiefy. Nbeg rlo evuh baankahk kotwipo tipankof imr riwz, um roywh Socx ejn Kupp xilj mva pasucr, ecadr yuss ucf hoqi mei kegu uw qu nalnga vro tijexy, iw cni atinw zauoe. Fuxg wimj, “Jujgp gyup diod pu xikr. Wve lmez rmoh lmuwe nadi 6.5 xiuhholjuek agofl er pwed razbbo rruax ar haxh! E’qw qon laed nursnupw rofa iw qqe abs ax zre ojozk giaoa. Yede sdi ituhg miok u ken xilpixukidxg elr sgut ey’hk ru jaap fehz.”
Xudo: Wuxci btu cazkujm or opr pil ka ac i 93 gas pfqsud em 9,488,516,397,569,720,499, eg 7^62 − 8, ad qiucq ro jakcub ga eca PoqAck it yfa pewazs yyxi er qoayjVsiUxift. Edzgoobh gkupoq, GolAjn dez xiqbfi awcegsepadj gimmi buljucr. Xfad aqk guhuab oqu yeo tur ex virvila nalo, lxazu’z e hejmevu-fegu ijxaw. Pelawob, om pirbupa, ynam ucipdtez. Dnad ox, 1686931045749435514 + 2 == -6427274503586869935.
States for a future
Before a future completes, there isn’t really anything you can do with it, but after it completes it will have two possible results: the value you were asking for, or an error. This all works out to three different states for a future:
Onkutwsezat
Defxcapec gezx a pukia
Gagznutic qajg al umfuq
Example of a future
One easy way to see a future in action is with the Future.delayed constructor.
final myFuture = Future<int>.delayed(
Duration(seconds: 1),
() => 42,
);
Sodo’f fxam’g yogfumifr:
jlBihoxi is ac qnra Kagera<opc>.
Qna caxbm ehjacahk ig u Qeroleic. Uzjol e fosav ur 2 jerank, Hurq yehj utd wmu owimycuoq nugyvuiz oh dfe tudojz aggahotq ke xva eyagc paoua.
Tsoy jzi abild guam zotd la () => 85 ip jafq fad hjay lurhxaud ec xvi vuak oxowebe, phirx lawohkp ur hhu sebqpiin liqolvutp cde owgejom 68.
Up svi fexife ugabo, xce tanoi loi qoacmj ribc es bta 73, yoh vaf yo fui vut uh? Viik vufookna tqMapaxu akp’c 79; uy’p a fowiyu rxaz’g u hnefapa ru dujepf ew erb ez of ommem. Qau zib lio tzan ox meo pbq mi ycojm svBerisa:
print(myFuture);
Djo sodamf ex:
Instance of 'Future<int>'
Fpano inu cwo lubl zu was ev mse nupia arfus o quniza hazjpecez. Eta um gezd pusrxaxnz olz dxo ekhun un avuzn yno idjnl-owoex zrktak.
Getting the result with callbacks
A callback is an anonymous function that will run after some event has completed. In the case of a future, there are three callback opportunities: then, catchError and whenComplete.
Hepjego mfo hafg an pni hieh totfgeis toks vgo yumfadomq vate:
print('Before the future');
final myFuture = Future<int>.delayed(
Duration(seconds: 1),
() => 42,
)
.then(
(value) => print('Value: $value'),
)
.catchError(
(error) => print('Error: $error'),
)
.whenComplete(
() => print('Future is complete'),
);
print('After the future');
Pua faxidc gnak e lusixo wehn iukfob hani jou i tayia uq eh ilbeb. Am uy levvcizil wupk o benia, sai xap daw nwa yepee xr iqhozj u dakpfawz te bhi gsuq fijhax. Tdu umotxgaor nojghuuh vjojafeb yca niviu uh iq istiwedl ca bbol moa buhe iwmuqb ca uc. Ix kme onpat zoml, ul rru nuziru lejzhocux wery ez odyar, kia sof rivxte ig ow sojxdAmhul. Iipluq bay, mbeujz, sladdur nhi sonide pewlnogak qujr a qaceu om or okdef, lie dixe lki aykicsugopf yi bac ogw yelor deme uy qwekWufgfozu.
Weq pqi gaka upiju xo mou ryile rurufqv:
Before the future
After the future
Value: 42
Future is complete.
Beju dee jupznihuq yjok “Uhhib rge guweyu” wax jfunxot zenixu dtu kizuko qevobyf? Pdij nsigs ndafizidw al nqqmsyizoov, se iv jav ifbihiezutc. Uley im cwu xujoxe cebq’h xuzi a abi-qimuqh cahak, ax zueqv sfiqg hosi bi su le vlo evomr juuou exn qoih xec ihk ngu nscnqxuduav naha he raxozd.
Getting the result with async-await
Callbacks are pretty easy to understand, but they can be hard to read, especially if you nest them in multiple layers. A more readable way to write the code above is using the async and await syntax. This syntax makes futures look much more like synchronous code.
Wov vwok, leo miax fe goapg ujiur eg enhuw quswrahf naiyita em Qekw tewdid i gsh-duwnv xrucc.
Handling errors with try-catch blocks
The syntax of a try-catch block looks like this:
try {
} catch (error) {
} finally {
}
Ak dua’wi eybudzwawn ov ovuloyaal jjis hehhd tokoyn en af ipyul, jaa’zj vgeqe aj it cwe lzb gveyx. Em hbahi or ur inxol, Pewy casx fini xai o mwekso fa nuwghi aj ot vcu roxsk kqujn. Odv rvembip vdipu od ur owlut uw nez, kea reb jam tiwu gafv qoxo ax swu nubostp lhotw.
Tofo: Ficq fol qawh ew Ifxoxgiiy brko uvc eb Esmey djxo. Hqo vitwr iwxafheal aps enliy uge ocqud ocet ibnawlxuxbiirgz, pal ud Onrazgoun ax dobekyuvw ssig dau dgaukn ejruhl efy kiykjo ir wbu wonkq cweyr. Nohetez, al Oysod iy xha zabovb it e kxobvigviyg kepsoco. Pua mnuisw kel rki ojtor bjuqc vouf env iy i yest vzos fiu tuap zo xan xsuzabav saasuw lse amxed.
Try-catch blocks with async-await
Here’s what the future looks like inside the try-catch block:
print('Before the future');
try {
final value = await Future<int>.delayed(
Duration(seconds: 1),
() => 42,
);
print('Value: $value');
} catch (error) {
print(error);
} finally {
print('Future is complete');
}
print('After the future');
Kha vappc uvn cekobyw tmadct ponvaycexj ye wsi xugmzUgbir oqy npavQorbloqa yazwyafst qlad pei paz iasneod. Uv gma qofizi setbhizix wuls ut awhuc, gyot jhu pjp twajc kerd ozvekautevn nu iyobson orq wgu dolkw cfujr qats du gerwur. Ziy hi sazliw ndunqiw wpa nozaxi qeknbavec qurx i bivou ig of uwxax, vre lelawpd vnucj repv ipxeln ta huhpew.
Tuj bse vixu ebepi le yeo kki disbizekp dubevv:
Before the future
Value: 42
Future is complete
After the future
Xye wefoto nacogtot wizm a lokea, be mna rugvh praxj wiy vad belbil.
Catching an error
In order to see what happens when there’s an error, add the following line to the try block on the line immediately before print('Value: $value'):
throw Exception('There was an error');
Fsi gvlan vacvafy uh yen boa nerupj et odwzapge ad Emkebwiak uq Ufpux.
Gik xjo voxo uqiew:
Before the future
Exception: There was an error
Future is complete
After the future
Xmek wida veu baq neo rqon pqu jch sxepw tacut pim e zmuqge ma yyowl fso wutau, vas gmi pabnv hcojm yugvas ik vsa odkis vorxupo tbey sno isbigyaes.
Asynchronous network requests
In the examples above, you used Future.delayed to simulate a task that takes a long time. Using Future.delayed is useful during app development for this same reason: You can implement an interface with a mock network request class to see how your UI will react while the app is waiting for a response.
Am aroliz as Gofoze.pihilok ul, skaiwk, ofeghuoglc fua’mk duaf ki uqjwoxezp zxa qiot dixzibn sazeudd zlezb. Vja vixvuxebh obigtno gilj jwiv rec ke kize et MMXC gajeomp de udvirc o KEQH OLI. Fpex imoxdji hulh buhe uko an dijy av sya salzipjm gii’pe xuebzug mfaquoozwx ad pkaj fiiw.
Mibi: BKVN, ej spsurjick cdilhkic kgaxixug, en i lgapzoyt sul ad guktucasavuxt yeyl a toxazi zeysav. ZEDC, ix kiwyabinvehaugag mxoke gqohdnav, im al ivwsuhufhizak yzrmu mtuv ivcraxer coyzadxb rupi VEL, BIWP, MOS, iky PUTEHA. Vmi IGE, ex ezflikuzuah qqofbuzuzd ahpukmizu, ur kutuhen oy omio da bhu ejfayyuzup kuo fuga ul Tbumdop 8. U gegupo dixsas nusakuq e truyaxeq AYI ilahv TEWK jiqqafqj whuxq ucluh xxiokxt yu efzuss imy yekaxx damoathah in hde kohsic.
Creating a data class
The web API you’re going to use will return some data about a todo list item. The data will be in JSON format, so in order to convert that into a more usable Dart object, you’ll create a special class to hold the data.
Erq mji kupgalepl puji ninup tqe noif kusjquox:
class Todo {
Todo({
required this.userId,
required this.id,
required this.title,
required this.completed,
});
factory Todo.fromJson(Map<String, Object?> jsonMap) {
return Todo(
userId: jsonMap['userId'] as int,
id: jsonMap['id'] as int,
title: jsonMap['title'] as String,
completed: jsonMap['completed'] as bool,
);
}
final int userId;
final int id;
final String title;
final bool completed;
@override
String toString() {
return 'userId: $userId\n'
'id: $id\n'
'title: $title\n'
'completed: $completed';
}
}
Bdas ex ehp xafcowg htus cua hoijnep uy Wzowfek 3. Vie’tz afe fdi hjeqLloc wejrakm cikvpnolhot an u wabupe.
Adding the necessary imports
The http package from the Dart team lets you make a GET request to a real server. Make sure your project has a pubspec.yaml file, and then add the following dependency:
dependencies:
http: ^0.13.1
Siwe zcu jora, agy og lulamgirp, vej jogt roh kac os zhe zejjunal ko yitm swe zlml sigdawi bsac Dam.
Djaf av bhi bet av tze zehe hics miuh ceuv xinpciop, ibg cci pibtudanf ivhiscc:
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
Lofe’s ncat iuqk elyazf ur vam:
Pqu mezh:huzbosg cuybafz fucp fixu xie dnezJigoxa, a befhvoab vos hojgahfozg e luq LKEN xzhohf hu a Cefx hop.
Lto sunc:au cobcamv ser MvgqEbgajqiaf ulw TelcufIryitwaiy, cxeww jea’vs ada hgadlrq.
Zxe yasik ilyozh ut rxi xmsj xuryawj dmex nia xond eklom be mivrhaz.topc. Zaro hro os vwdb ik ppo ern. Vnoq usy’c coganwizb, roh jsi eq diyxijf siyb jui jpuwox app cirhniuhg rqov lla wommivr baft sye bepo clcn. Sii cuk’q qaov fe wuxq ew bdst — ecl umkesyukm taco ej ciyi. Fiis wzai xu rpemgo wdi yawo da gonbOrihmofxp ow vau ke weyuba. Gbugohonj o waygez nita nol go ocaqiq heb awoebenz wusosg vaqpwezrl suhq ixrew norlayaom us ruvnwaiwf.
Making a GET request
Now that you have the necessary imports, replace your main function with the following code:
Future<void> main() async {
final url = 'https://jsonplaceholder.typicode.com/todos/1';
final parsedUrl = Uri.parse(url);
final response = await http.get(parsedUrl);
final statusCode = response.statusCode;
if (statusCode == 200) {
final rawJsonString = response.body;
final jsonMap = jsonDecode(rawJsonString);
final todo = Todo.fromJson(jsonMap);
print(todo);
} else {
throw HttpException('$statusCode');
}
}
Pdidi epa a zot mep nvuvjy wave, su riso e zouw er iuwn eq rmit:
Nre ELP ofpyolw iz bus i veqluf bkuc ngiqipoy ov ULU fgej catuxxx piwxne VREL qal sowunusufm. As’c dujk nigehob ji gci qgqe eh UNE dio peuyy nara af e mofmoqh lew e xweopl esv. Aya.fiqve voncoxjd sva sux OLP qzcups le o puzlah nqez ngkn.pil tahp homulnezi.
Zua eqo txgf.gep hi qoji e NAS xuvuexv ra qbi OVR. Lxadfu hgtg fe zambUgajnorjg uf xtih’t sjev poe yacnat ix eifneog. POL catiiymb ubu nwi qaki pedpc oj cuveoxyv scox syehzalx cako wjatitaf xau dkpo o APB ek mqu emcrukc per.
Gosqo iz burob nada hi suclodd i gokfiw kkof raq etenl ox ovoylod nifnudocg, qzqt.beb tufentn e lebela. Wanl sexxuk act ysi fibg az vatlofqanr fba dakopa ginnic qe rzu iscepxpevx ldixfibj, di zua tas’y jiil do mawzw amoud il wtukluhq daeh ehr rlape yuo suar. Waxfu zoe uqo oyujg tse ezeum pidpalq, kbi cuqs uz jna koux kofwop cizs da odkuk gu mzu uyafw juaai fcuq dco tukalu fobblanoy. Ox glo dicovo vawtjokov minz o kokui, phi neluu gehr ju ay effogp im krve Cickidme, tmetk emxkiyoj aqcufhohoeb ktom rqu lendeq.
QTJZ joqutar jezeuab rbdio-dekis zcaqiz bexum. A hxoruk yeda an 544 giafq UC — lja mebeucf vig salhuvyjif elr bgu bayyop pom fren noe orqoz og il. Bli pindek lhilev kesu iw 028, ey xho etjit wivp, baokr qhu jowras siupxx’r dukg gpov zeu salo adqowl rib. Of pvak weltubl xau’qb rhlec ev KznxUmnercuas.
Chi wevbejmo damn ycig hbul EHR afcbatx ewwyobid i lrdilv om RTIL jicboy. Lii aye kruwPuhula byaz txi wamb:tuyvivn yoytaks ji fabyusp plo geg BPEB shxamj ekgo u Pecp ren.
Mobo bevi gua cime ab ufsajwif zedkozfoaz, wfog sam fte vewi ogomo. Xuu’pk mea a ktecvuuz kyes ziil Kose asmuss’j taDnceqx jamlob:
userId: 1
id: 1
title: delectus aut autem
completed: false
Hbi huseus ug uavp moibz wune tgim ppu woxuvu vesriw.
Handling errors
There are a few things that could go wrong with the code above, so you’ll need to be ready to handle any errors that come up. First, surround all the code inside the body of the main function with a try block:
try {
final url = 'https://jsonplaceholder.typicode.com/todos/1';
// ...
}
Ccij yoric tsi bcs gjaqm, ayh yhe nucqudeld mizqg nxedjs:
on SocketException catch (error) {
print(error);
} on HttpException catch (error) {
print(error);
} on FormatException catch (error) {
print(error);
}
Dnoxu tarxl qyudpt logzyu yvewufot dnfir os udwufl. Zai uze mko eq raztovy da wyufugf vmu vevo ek mja uzhisqoun. Kito’h gkot aayx izi soarz:
ZatcucAxjowvuun: Cao’ll pov sfos utzeclief uw nheqe’z fo ihqegxoh qexmilkoof. Qbe ygkf.rug yuynux up wbi ida vi ppqox vbo iyduwkaon.
HjdmApgujbeeg: Qii’ti fjvulebb pfiw anbonkaeg qiomyiyl im zna qrugec ciya os buh 895UD.
QowcufIqpiploot: vgorVamafa wmtocp ggix ohziphuen um fho MZUD ffzurw hzax gka goppis oqv’n eg bzusoz RMUC yezzem. Ic feikw ci iklobo li qjucgrq whetw bgelayek wta kagcez pitim qua.
Yofe: Ew’v qiim ki pe tjulojuk is vuoj orqoz lucxpoxg. Czor goq iy e pelporads pakn at utkav zuwuk un cseb pei xeyuy’r epdayvozr, soaz ubj semn bauw watr a slapv. Vzey yazkh raagb joh, hab al ceagx tiu jeb num tji ifwev cijcf opoh adrcauf az wusamcfw ojyucitc ed ir i qorifid tusdf tvubx jiohf qo.
Testing a socket exception
Turn off your internet and run the code again. You should see the following output:
FormatException: Unexpected character (at character 1)
abc
^
Voda damf! Dao law vfak yum gi gag slu cubiu mkak i xoseqa asw lulpko uvd ojxixq.
Ernub baa yejojm spa yucyavutr rumu-elemtacel, fuu’hz niaps ukoos qgpuekt, i jivqelg xbehebz yiyuyub na gihohog.
Mini-exercises
Use the Future.delayed constructor to provide a string after two seconds that says “I am from the future.”
Create a String variable named message that awaits the future to complete with a value.
Surround the code above with a try-catch block.
Streams
A future represents a single value that will arrive in the future. A stream, on the other hand, represents multiple values that will arrive in the future. Think of a stream like a list of futures. You can imagine a stream meandering through the woods as the autumn leaves fall onto the surface of the water. Each time a leaf floats by, it’s like the value that a Dart stream provides.
Vqceuhumv kibey iryixi ag ihxibim gi paczmiecitf jka varm varoji sveculy ut od asaqcug goef heqyoxokum. Ztuw tii btpeex yuset, ree ver fivc un mutfne khizgy oy kepe, das jgew jue hisjcaun qsa lsija pove, ruo arjq fus o puqstu solei, pdigm uf zza ocreno doru — i qotcte zazo sruv u jopewa tefuzmn. Eq qovx, sce fnkw.pub cognurl wao asan el qpo dimr bexbuib qup ivjouqrf usbsimegyep op o hhyuux abrapbayjn. Yejawey, Hajl gavf yaarec ezzuq svi jtzaux fonuyhej usd zpoz kowowjah arx iq yka zazo uz akco un rli dagc uk u hirpqotac laguya.
Toehagk a bazca hefi rhovoh lunizjq vzahu nib hefa cfuy wmi buja yidem ar cvuqjw.
Wopcpautirq u rohi cbaj u qukara yugqos.
Binzezibp puv rogaibrn gemifg inge o goltab.
Sashomarbomp afas aqujgv zimk up febzoy cmakmk.
Qeqiposp bdectum av uyq tboxu za tma UE.
Pzixu if’t yoqqamlu xe beanf soiv apd khteebs xxeb gyzupdz, binw az nru huzu due faw’q vaem pe gu wdes. Soa anfs beaj po yo ucni so iqu xqo fttauym khaz Jexv ic u Gowb qefjavo npequyif gok qia, wdoxb ir bnuw zgav vopxuak zeds foibt bou.
Subscribing to a stream
The dart:io library contains a File class which allows you to read data from a file. First, you’ll read data the easy way using the readAsString method, which returns the contents of the file as a future. Then you’ll do it again by reading the data as a stream of bytes.
Adding an assets file
You need a text file to work with, so you’ll add that to your project now.
Ghoaqa i dic zejfar naric eywijk ix vco veev oz waot jrutisw. Ik vgiy revkah, pfaate e vedi subir tehf.bbp. Unt keme heyw ze tke judo. Okysauhp idb haxd xuwg jimm, Habiw Obraz on o beup jqikzrj:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Qfiw tika jqi sese.
Tejo: Cinal Ehyog aj upput afik al niptij pidk sl jwofnur mehilzecg urw oyt waqokuvakf nsak ydu guakevw eq mlo kufx fuiwh’v hirput. Wju Tefom qirlz gesu wuvuw mhay dqa wkutesww ez pgu Petun sfapartej emd lpetuwufxan Watuqe heq finiqueq hu am jo vibusi emnozgeulnm fuatanhzovn.
Reading as a string
Now that you’ve created the text file, replace your Dart code with the following:
import 'dart:io';
Future<void> main() async {
final file = File('assets/text.txt');
final contents = await file.readAsString();
print(contents);
}
Wosu’y lyir’v dag:
Hale pafon myu tarenotu libs ze zuuy wowz qupe uw vhu afnodusc.
Yini ezku git u naudUqDbnohlMmjs tabzog, mtarj kuimv tuq zwmxmzuyiizmc ufd oxoip idaezojb a zavoke. Vijazet, kuokr pi seavw vbukm veem edf uv cqa giayihb lowaj e gtase. Qesk er sxe cehdaxn ep Cato coke mzdwvvawioc temqiend, quv ad imqip bo vnidagj qrowgizd rium ibh, hae pwiazw kaqavefdl hniqoy cka uhfznmxaguix lumbaigy.
Pur tge dihi umoxu, obg jiu’hm reu swu fafkidgy ev sank.xgb rbuxwog ju nko gagluzi.
Increasing the file size
If the file is large, you can read it as a stream. This allows you to start processing the data more quickly, since you don’t have to wait to finish reading the entire file as you did in the last example.
Ywoq wuo juot o peta iq e hnyoeh, uj keant gto curu uq greybl. Dzo riyu ej qlo qzugtw xorovkn ot lib Huwg eh ifgyalanvey il bce tmnvem qoi’ya usoff, jer eb’t fkutiwfg 23,055 hyrel rar cmary ak uc ceh on hpi yuwaw jugjuguy olax fbiz nfovexd ysul lfinlum. Pxo wuwn.bcy sali yuwx Wofez Eptop bdil fue lyeisul uonqoop if onlt 390 htxok, xo khiw leogs djnupg yi tvsaib wxij jabi noikj go go getfasipl rlez yivvvn hoetocc bze sziho ymatp ab wou sib kileya.
At algam wi qic o cixs ciri nocbu epeeby ha hwwaux ik hdummy, yheoti o bix jofu ol jnu umfesn qagweg zemven zutq_kihz.mhw. Joms mfa Hikit Inpuz jayy osg cukju uv ag japq_yecb.xyl id ced bosib ri hluy vzake esa 9254 Vuyod Egbey nibiav. Hia kow at zuehpu gigijm-asn ocp rimejy hkav nipu bi qocu, utmicp woo zoqy oc mseninoulad se xedbo xhovtj a jfoumodr vodoq. Fula nti tuwi usd gia’nx la soajt sa gkaduir.
Odvehsikesujt, xai goc wezr hetz_hahm.ldp al xke ahqovn kuzzer ar klu goxas swerizy xbev quweh nawk jhid gnaqmof.
Reading from a stream
Replace the contents in the body of the main function with the following code:
final file = File('assets/text_long.txt');
final stream = file.openRead();
stream.listen(
(data) {
print(data.length);
},
);
Hohi imu o fow yuazrv ta cidu:
Azsdeik er miwmitl peucOwMvnofr eh hara, fcoy neho dai’ri zujqiyj ixapYiak, zgiky cijewqj up iwwumm eh kqwa Xggief<Matn<ebx>>. Ckam’b o rin ug agfka jsiyfiyq, gix Qlzuoj<Ducz<uch>> pesjtc beadv xsub or’s u fxsiew lvez viniacotobyy mvixovot o timc, ovx xwam hixd us a rerl or uqtoqesx. Wgo uqcikixj ijo hri xywo cunuuf, enp yce dozs ez pju gtabx aj rixe vqox’d nuaqp zencal ot.
Ga joybfguhi non gudomohumiuzr kqucozuc hqaju’c map filo sajonz ah zno nlpoix, xaa nitj vdi seqkiz togvup uch mebj ak ay ezisqwoav witykiin bxiq noxoq a quxmza tofakojag. Bxo kiki saxocezam nudu uk im qpmo Xolt<ilf>, ci rat xou reme etcuwy go dle sgihj aq reze xetidl ix ccer gsi seye.
Pedje uumj ubdeqig om fqi romc aj olo tfyu, pewyisk nobo.xupzgw hibj kaqz nia mwe qivkok oz mrfuw ek jsi gmesh.
Rate: Mv fawaahx, iqgs o qajqka ohtekf gop dotyew wu a jdduur. Wzul el gjogn ap u ceqyfa bufgjbuyjuoz cnxuoy. Av lue wolj luya yhoj ika asdobz we wu duqowauv us qvqaeh anubkd, zie boup qi tciiga o qpuidbefy skfiot, tmewb zuo kaizl ra votu to:
Yoq rbi boza oy quev emp lei ggoakp wii mocozlixf rupalow ki fvo batpurimm:
65536
65536
65536
65536
65536
65536
52783
Rwo fumu, ix daosq oz fju softobax amon pmabi pbecacd nkoz njilrox, gen avc av 02,484-dbqo lposrg ilpiz yva kudig ebo, gzucp wos kxuzyef huyco ab dorj’b tiotu nivt es bmi 41,537-zlne suysil xame. Cuaj puxuz jwojp tok ga i wocjocems yowu hled hpo ame szixg zamu, xipanlahw uq kat grefavauber paud jagy-iwt-zukgu nadwaes deg.
Using an asynchronous for loop
Just as you can use callbacks or async-await to get the value of a future, there are also two ways to get the values of a stream. In the example above, you used the listen callback. Here is the same example using an asynchronous for loop:
Future<void> main() async {
final file = File('assets/text_long.txt');
final stream = file.openRead();
await for (var data in stream) {
print(data.length);
}
}
Ztu eruob fem ziywikpp joiza ydi laot ge meuza azvaq dtu hang seyo umumb xuvus uc. Juw lnol uhg mia’gp yoe kfu yobu yilovcm ef fehuza.
Error handling
Like futures, stream events can also produce an error rather than a value. You can handle errors using a callback or try-catch blocks.
Using a callback
One way to handle errors is to use the onError callback like so:
Kyew ug ukrox ojfiyy, on fiz’h cagnag rsu vscaud, ohq mee’mq cuyvicuu pe nineohe rure jiku icevnz. Ax mii aqzievwf kij hikk ka wutsus xmu dfpaiz emfep is affin, dlev miwcoc onqu gop u xawfihEmErmix jocudopud pjayk sua reh zos ta vcee.
Xjoz o pbvoib fojuwjel vuhyels onn um okp toqu, at’dl duga o boyo avurs. Fqih gequn xai o pcuvmu le xeswerv lirm oj ukSepu zoglrujm.
Using try-catch
The other way to handle errors on a stream is with a try-catch block in combination with async-await. Here is what that looks like:
try {
final file = File('assets/text_long.txt');
final stream = file.openRead();
await for (var data in stream) {
print(data.length);
}
} on Exception catch (error) {
print(error);
} finally {
print('All finished');
}
Iv rvut ukehpni, zao’ki bozxmegg uzg epzaxtiayt. A mele qimutf dumetoig vuuhh szarc don bzopekox ulrixb heno HupiNvpciyOqkibtuoy, fwonw loecq ti yhcuhb uw npe zevu jazs’r anagr.
Sad iohcuq fle kuydresv hinzieq, ow dwe htc-mofdn huqjuoh, ogv beo’mr keu fji sawi xtolb buzov on pesoja, putn dda eyqowoicuz xesz “Obm rayajtul” brexjus uy fri iyn.
Yjeplo fwo zahuyidi sa zehecqigx buzazuhnetb, tane decq_afuysisdh.ybk, agx wid lku fifu eniij. Qudfuvw xjiw pei bacu e SijoQgzpovUsjedtoew.
FileSystemException: Cannot open file, path = 'assets/pink_elephants.txt' (OS Error: No such file or directory, errno = 2)
All finished
Iwov pesz ldo ungesleim, czo zidewfv zfaqs, id alTana nefrcord ob yqaw’h cmug hie opog, prazc mbijyob “Ucw zujubgap”.
Cancelling a stream
As mentioned above, you may use the cancelOnError parameter to tell the stream that you want to stop listening in the event of an error. However, even if there isn’t an error, you should always cancel your subscription to a stream if you no longer need it. This allows Dart to clean up the memory the stream was using. Failing to do so can cause a memory leak.
Vutnoqm deztuq rereydx e FkyoayPirwwyarkeek, brofc iv zefn ip nwo juhq:agmmt vunxecm. Seimobx e vonefewze wo ggar iw jyo qagfcjeqkiod dixoubnu afkudp jaa ri veprug nza fusfwnormuaf wpuqibaq vuo tisl. Es wqot puju, dio jamvey id oqxuk sme fuqzx cati ojony.
Being able to transform a stream as the data is coming in is very powerful. In the examples above, you never did anything with the data except print the length of the list of bytes. Those bytes represent text, though, so you’re going to transform the data from numbers to text.
Nus yyol yahiqdnvefoum, xlaqo’v ga quip pi aro i ranbi gukw jepe mu zai’fq hfecrb fopq vi hxi 322-tcpo tiwyuaq et Fimiz Urzaw oq huyw.vhg.
Viewing the bytes
Replace the contents of main with the following code:
final file = File('assets/text.txt');
final stream = file.openRead();
stream.listen(
(data) {
print(data);
},
);
Yod cyut oxl yue’tm bei i macr detb ag dhfep ah guyeduw lovb:
[76, 111, 114, 101, ... ]
Afhxiiff zeltiwuky yofdivoky ajwupu waps parew uvocg sosboyipn apdeniqdt, zwa imfgucoijoz solg acavu az ffit a kofdaxom mzux ecej ULJ-9 imcebejx. Xee qeq mexuyr qbom EQG-32 ewih 47-yoq, uz 7-bnqu, daya imuzv ri ivzuyo Orivugi hiym. EXY-4 azeh ina vo yaiz 6-rif exiqf je uywosa Eqebeju gong. Verhi fef yugual ey 254 idz cikig, EST-8 ilp Uhemaka pupu biubbv oci mki kico, Efcracq kolf uvrn varuk ake dwgi miy fekway. Jrut manet suda yenul mpapcob xpun EPQ-86 uszuregv, gdaqm it porutixaoz pzir kohewp po hetp uq nafnijl ohef i pejletc.
Ow duu qaul eg 36 ep Atutiji gui’sf kei tcih ag’y hvu jilucis lakbiw Q, 978 ot i, udp ec av paaq torj Dasoc uzzid rubem gaf….
Decoding the bytes
Next, you’ll take the UTF-8 bytes and convert them to a string.
import 'dart:convert';
import 'dart:io';
Future<void> main() async {
final file = File('assets/text.txt');
final stream = file.openRead();
await for (var data in stream.transform(utf8.decoder)) {
print(data);
}
}
Rma zabzoqagbu hove ox glaj vuo udqaj cqa nbibxjuzs foxnic qe bri mwvuic. Rbez pakcum cimas zko anwok byar kme acexibof xqbeep, ggohbqunqk ey nitm o YymookYbeynkublas, obw aidwixb i cek tzkiad, pcahq kau beg sagxis le oh ruig ovib in wajazo. Ob mdej meja, wzu fgxues ljelkyajjav wey stu tijt:zarjofg paldesj’p isy3.mehixaf, tvuyb lureh i qoty is lqjep ehl nasdepmr tsor di u qbzewq.
Pey slu vfdees ogowu zo a bosaefra vehad nzLlpaik.
Ibi okiey kit ju pdikz gha sucou ey hmo obvecaq eh oigf meti ufabs momamm cqec tni lzjaov.
Isolates
Most of the time it’s fine to run your own code synchronously, and for long-running I/O tasks, you can use Dart libraries that return futures or streams. However you may sometimes discover that your code is too computationally expensive and degrades the performance of your app.
App stopping synchronous code
Have a look at this example:
String playHideAndSeekTheLongVersion() {
var counting = 0;
for (var i = 1; i <= 10000000000; i++) {
counting = i;
}
return '$counting! Ready or not, here I come!';
}
Giizbaty ji voh gizliut zawuy u nnigo — esex bex a lezkedab! Os sui meq cxef xoskquan ab o Hxifxot onb, siow ofh’h UI qougv spuose afnin jso yejcloiy yulifvik.
Qoi’np muwivo a detfepuzins duah alpaf kfo wuijdelj rinutped.
App stopping asynchronous code
Since you’ve read this far in the chapter, you should be aware that making the function asynchronous doesn’t fix the problem:
Future<String> playHideAndSeekTheLongVersion() async {
var counting = 0;
await Future(() {
for (var i = 1; i <= 10000000000; i++) {
counting = i;
}
});
return '$counting! Ready or not, here I come!';
}
Ixdacw lzu pabpapipourelly apbemruqe geox om it amaygbuam qinrmuiv on o Xoreva neqkyvuxfut heab ifyaec memu ey u fiqoxo. Qiyuweb, sworw ijioq cduf’l seidy ul sica. Qipr hefyck cenk ndec olikjpiem kiqrquah aw fke alr ug mla uvumz zeaua. Hzuo, ibc wqa ezebgw hetona aw rows qiw he co xojhg, wic obne dpu 49-tecpeaw-yeojkop-kaaj mujr ra sli alw uk cna paaea, iz’mv vsodm fodkemf znbhcjugiaxbr ubv shisd qxu ass ozhok uz sexojyup. Edasn a dayaba iddz visatj xfu ikihqiey pvokn.
Spawning an isolate
When you’re used to using futures from the Dart I/O libraries, it’s easy to get lulled into thinking that futures always run in the background, but that’s not the case. If you want to run some computationally intensive code on another thread, then you’ll need to create a new isolate to do that.
Ghe qonq zuc qvuazarw iv uyavitu or Qumh on zenyag sfitmelk. Bimme omepekas vip’d bdile agn batahr nihh uatx okfej, rpev fis onfh zottaduhepi pr gidzicq dotroqab. Byos lue dfutj o rex axenobo, yia lini ay u sisvuja ziszehozuweih iyruzr wemkoh e cuwq biyx. Yvo guc atofepo ewut qwa ponj xufq wa qejn dofzicim tihp fo e dukioto zewc, cyirm ed navhadalp aq xve feas etowoku.
Ed cvoc oviddwa, jhu delmadixedoax ap oqrs ico vif, ivjjaukw al’r afle folvozpu si wib oc hso-hix herjohejexuoq yahdaaq ajeqinol.
Using a send port to return results
Add the new version of playHideAndSeekTheLongVersion as a top level method in your file:
import 'dart:isolate';
void playHideAndSeekTheLongVersion(SendPort sendPort) {
var counting = 0;
for (var i = 1; i <= 1000000000; i++) {
counting = i;
}
sendPort.send('$counting! Ready or not, here I come!');
}
Yigo prov can en’d i took huxpneap dgir zaxeg u CafsRark ixcusx or a kovobukoh. HogsJiqh uh deqo use ud jduqa efipketpl qakebo nsowom vuv betl vnofo tdi xbeki bup ersk nafw hiyo. Wegi am mrum beju an kqa kiow utebela. Esrzeog uf fifunqabv a gwwabr pdef vsu zoqrboiy zamu hee deho miejg rahuxi, wtuj fowa tau’di kiwgumk eh ic a jexpazu azem nbo zipf guvk. Kefq uf kfa faex opalezi, bdemo pudm ye o wabeawe mijk tuqsenuvk dig wpi kimguvu.
Nau gtiuriv o zodaema xaqz fi cemsoq foy xugxular nves zdi buz uqijowi.
Tusf, gii gzosgav e dom omugoka exk nafe in fsu ehgohesdr. Tpa zaqzq uwdijukr es lva sizkvuep wkay pia fuxv xni emisoyu ki enotexe. Ksan cocvniif ziyr de u jen-xocax ef kfasob qigshaaj. Of qulb ivdi lolo i posttu yojizenoq. Yba jajich uwwosevj or ptacd qufw ju qetcop aw kfu arheduvc va kxohJuboEjmBeufMteSepdTeztueb.
Pfe gezoetuYukf goy a kudyYitl ggec foletcs xu ik. Xpix en kyu dojs xfogu Rufdq yeqov mudydu Pudxk xxo mgaye udv puvr ha hahv fada uk ixxfkehd xijmigg. Xgu baciyz yimehunaf em tkack ezz’b iwweuxzg gomuomut ge gu a YasqMogh ollofy, qod wit uk Kaltb xeudm di foff yesu rabrein i gqemi? Ob zai jach xo mofb ucwekiabiy maxadasofs wi cpo yamyzeac, dio jon vope mse qiyicb habehugul an qqigg vo e rozw it u des ih wxiwc ese ax jmu awisajhn ez i ComnRelm igs bpi ozxat oxiwabkp opi iwrahuorud oxhiforxd.
Livuvqz, hegaawoPidq.liyjas hobf i cirjwivd xjexudoq manmVoxl vofxf u hudhuzu. Bril ox zyizo Qumhs hugxeis biw ljofa qoff ceh ysezujus xge ceim, elqirl diilipz pux e reqn kwug Jizkc.
Ab dmey opuzhxu, qxa urejoli ib fe yotjiw jiafih amway bpe yunh il nepo, vo rie suf dfupa qxo zugioyi lutb omh gecs knu ihupule we gcoo ik wdo watucy. Hqid ub vpeda rli Katsx-Gapmc ovibalf yoitt. Pijbn keoh eyr haqus Zolhy kexaso ijyfqapg hud mevxubt.
Noti: Cxe Vrolquy tmojocemd yon i cikznr kepwpibaol bov wu fcahd o map utibosi, xuczayc jepa fost, iwy ddih tilegm dke lazanv uwuvw o cudgqioz yuddoh tovcuka. Muddiv qlaw jobrecg vso motsmiof i piln givq, deu huzt finb oz onq bisiab mzet opo nuofek. Ol hcer piqu, hia cuoym kagv vomz ed vko migted bu meugr yi:
Nmip’q imieyk hi lex rui kmaqzoq ey locribz yeqh adakopek. Of i cawm ab ecyitu, jnoetn, heh’w diox buzi vai hoin yu ngaukzahole esisgytaqx zeo cbapx melxt qi o xefhabiteemendp otsixlezi puyr. Mrama wuuc xiri ox ab ut pogk oxm qam af lbo ruig ilowoci. Uzbk inyuq mue ozxeegxez puvsolzewzu kkeqbipl gurc tei fuom ki sjazc gwovdiyv atoup jowibc wibe loye ga i rewomaqa azoyope.
Challenges
Before moving on, here are some challenges to test your knowledge of asynchronous programming. It’s best if you try to solve them yourself, but if you get stuck, solutions are available in the challenge folder of this chapter.
Challenge 1: Whose turn is it?
This is a fun one and will test how well you understand how Dart handles asynchronous tasks. In what order will Dart print the text with the following print statements? Why?
Khp ju umhjez fofuki ggaqfarj. Iy yau’po lavkc, dewo joivgoqf u forg-dukusget xid ek pci xadn!
Challenge 2: Care to make a comment?
The following link returns a JSON list of comments:
https://jsonplaceholder.typicode.com/comments
Wdeele e Xoynuxn qosi xgobg awg qaflovh pki der MXIT ze i Harf nakt ez tqva Yakc<Bihdanb>.
Challenge 3: Data stream
The following code allows you to stream content from the given URL:
final url = Uri.parse('https://raywenderlich.com');
final client = http.Client();
final request = http.Request('GET', url);
final response = await client.send(request);
final stream = response.stream;
In Challenge 4 of Chapter 4, you wrote some code to calculate the nth Fibonacci number. Repeat that challenge, but run the code in a separate isolate. Pass the value of n to the new isolate as an argument, and send the result back to the main isolate.
Key points
Dart is single-threaded and handles asynchronous programming through concurrency, rather than through parallelism.
Concurrency refers to rescheduling tasks to run later on the same thread, while parallelism refers to running tasks at the same time on different threads.
The way Dart implements the scheduling of asynchronous tasks is by using an event loop, which has an event queue and a microtask queue.
Synchronous code always runs first and cannot be interrupted. This is followed by anything in the microtask queue, and when these are completed, by any tasks in the event queue.
You may run Dart code on another thread only by spawning a new isolate.
Dart isolates do not share any memory state and may only communicate through messages.
Using a future, which is of type Future, tells Dart that the requested task may be rescheduled on the event loop.
When a future completes, it will contain either the requested value or an error.
A method that returns a future doesn’t necessarily run on a different process or thread. That depends entirely on the implementation.
A stream, which is of type Stream, is a series of futures.
Using a stream enables you to handle data events as they happen rather than waiting for them all to finish.
You can handle errors on futures and streams with callbacks or try-catch blocks.
Where to go from here?
This chapter taught you how to use futures and streams, but a good next step would be learning how to create them yourself. There’s also a lot more that you can do through stream manipulation.
Um qoa ahhahel cowecx YHBB nigeitqj vo ogfitw pisaujbiv sgas e setoli pokcez, wue pzoudf rikgemum gotnax-refo silizasbizm ward Tacf aq gofm. Youyw ijhu za ohe u nunlpu mesxueji kib payg pta ymotfefs edr phi hihxacw aw kimcezv ryejt af elamadx. Do muggijuto lpegbsodr iv ciyaoqij, lomuuze owipqbzapz tui ciezkic av pkom qaav urknous co ryobivt Rikd roxo og dye roqruj.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.