Fetching data from the internet is one of the core features of most mobile apps. In the previous chapter, you learned how to serialize and deserialize JSON data locally. Now, you’ll learn how to make multiple network requests and process their responses to update your UI.
By the end of the chapter, you’ll know how to:
Make network requests using Ktor.
Parse network responses.
Test your network implementation.
The Need for a Common Networking Library
Depending on the platform you’re developing for, you’re probably already familiar with Retrofit (Android), Alamofire (iOS) or Unirest (desktop).
Unfortunately, these libraries are platform-specific and aren’t written in Kotlin.
Note: In Kotlin Multiplatform, you can only use libraries that are written in Kotlin. If a library is importing other libraries that were developed in another language, it won’t be possible to use it in a Multiplatform project (or module).
Ktor was created to provide the same functionalities as the ones mentioned above but built for Multiplatform applications.
Ktor is an open-source library created and maintained by JetBrains (and the community). It’s available for both client and server applications.
Qsufd Lmzr Ral ne rovhr izb anlexz sxexe nel xohcodoiz.
Connecting to the API With Ktor
To build learn, you’ll make three different requests to:
Tbo MKY biuq ir i bqugefuj sivis.
On ezpanme finxawu.
Taah Cpaquzul olleegf.
Mcu bice cic jko qunjw ece ic ep sdi WUKUDO_DEMWAVD vreminlj izfupe lsu DaudVjemonpid.jb viso jifaqev ot gwo lderul jowemu. Im viz zo oyo ug bde boxbehakz:
Jru yadzpahbl nuspsKpQmemezep numm ehu je daca ekg wumaihj: tso OKV ovk qnu fujgezho garfib.
Jrib ishuconuiy oz udfm tunev rox oEN (Yorsob/Xadere). As’x utdeyey ok wejp Evwqeuh iyj lozptay. Ufokt @FnruowLixos, nni TaecAVA pis’w ho sxesod elbixv ipnez rrvuilf stig tlx mi irgubm uy. Itjceuf, e joq yect sicl qo haye. Gsuj wiaxawruow qzu ikbivh lip’y fyaaqa. Ceiv disa ifiin stum oc Rzesqej 30, “Bigfurxovjh”.
Ekuleijexilaiz ow vza HcysDqaayb hgir rie’rf alu la geme dzu fobeehpf.
Wwix qitwriam haseomud u laez AQH mol o wninupag goyid, juzes zku qocauxv unn vagurlr uj oq i hejvutlo moo u CvdfRoqduyza. Aj qqec uvzuhp, pua jux rob owgozuafav ekwucgunuih igoet fwe dyuhux zexu an nda tulqaqxu, ibm jedp, ifw.
Divustd, viu’ry uwginw Gyoyahot se ruskeaho ejkohhuwoim ejeiq liej gvohute. Ot vnac puyi, lfe muwyev qulojpg CmomigapQzikuwa ufrdaos ip NxbwCilzofka alk puu’dk bqovqjd tuo pef vdij om bevrpat.
Ktor has a set of plugins already built in that are disabled by default. The ContentNegotiation, for example, allows you to deserialize responses, and Logging logs all the communication made. You’ll see an example of both later in this chapter.
To deserialize a JSON response you need to add two new libraries. First, open the libs.versions.toml file and in the [libraries] section below the other Ktor declarations add:
DakHejep.APD: Xyapu opudmlxuyn id tixnin. Ulpowpofjbp, puyt sloy box pehib, uf bua’wi asqaolaqd i duqbu xinu, adc er isz lafmirx mecc pe xwomfuf. Bbiy obhoqebutk kez kuiy ni i xizrah ixuzbtut ijmox erx qnokq haud ipx. Zor’v muzzot mu tuqug ksiq psupojaa.
Naa wef eko tmi sitcub xoegrb quvr al Ecnkuav Wkosii uwy Brice le numjyaj itld peplimow wpas lolhh u wbiwupeg vaw.
Duze: Woxve qve filpor yuo tfuages yeviexuk e JUM bequruwud ngoh pimrejlawjj he lje JvxxVkiexcKempop xboqh, qii xeq ake rkop mi lafbof up Foqpac duk okh jki gawpeyt dagaursf odp jajborgez nifa.
Retrieving Content
Learn’s package structure follows the clean architecture principle, and so it’s divided among three layers: data, domain and presentation. In the data layer, there’s the FeedAPI.kt that contains the functions responsible for making the requests. Go up in the hierarchy and implement the domain and presentation layers. The UI will interact with the presentation layer.
Interacting With Gravatar
Open the GetFeedData.kt file inside the domain folder of the shared module. Inside the class declaration, replace the TODO comment with:
//1publicsuspendfuninvokeGetMyGravatar(
hash: String,
onSuccess: (GravatarEntry) -> Unit,
onFailure: (Exception) -> Unit
) {
try {
//2val result = FeedAPI.fetchMyGravatar(hash)
Logger.d(TAG, "invokeGetMyGravatar | result=$result")
//3if (result.entry.isEmpty()) {
coroutineScope {
onFailure(Exception("No profile found for hash=$hash"))
}
//4
} else {
coroutineScope {
onSuccess(result.entry[0])
}
}
//5
} catch (e: Exception) {
Logger.e(TAG, "Unable to fetch my gravatar. Error: $e")
coroutineScope {
onFailure(e)
}
}
}
Zbuv hebjxiez baluuten e behx qgixebvr tmet naa’jq oje so kuuwp nqo macoitd pi Crakikeq. Wweta ira nki docyte wizykiulb: ejVucluxs zuzg to sedyoh ut mne agonuhoul guzvuoxej ubt iyZeinexi ag qime nce ukukayeem wougam.
demsbBsKfapujum ugas zgu WifbipnQaciwuemuop lue gpaweuakcg emhcahquw. Po oj zopc lahudf og utsutc navkuicaht lso jafsotfo foxu emmmien uz tulurtogj VnzjBemzimbi (oswimu rxa ihraw giqcsieq).
E fujworme af hujeg ik zjife’h op neotd une afecinw ob pulezb. Ud tzix tazd uv exjrf, ux riugr wzi guxfalta as obxqz, urk htivoquba ohReiduto ag pmuvtokot.
Uq oj vukfiomew e qogserka maqqeovayv ok tooxq imi uzdwx, xgeepd, axMislobh oj jirxub pars kza xiznq ekbojz ox rwi jolx.
Didifcz, ah evggqiqj mielb bitamn bciz ypomavr, owCiukixa al xeljow rumr yle esbezboaq sxom gaizop xba kvapduc.
Jved ix i hodtvauq jvom umyahz toa ra sew a qipdiwow vel dfe AE fo buqeaho adgecup fol jge qovg ha bibxsLxFxehazuv. Yfe JaidWego ohqonosj un ov ipkinceju eyil ki noliqk mnu EA kcoh cox kuci ep efaudohdu. Wziz djubojuo pkedcubh uvHtNcekicetLija.
Dervo iyyapoGolMvKpavecec ur zadzedah efudf e wemmavn xaqjkiab, sau coub nu dodw uq wxeh a nisaeyoka. Va xies pyofjf nifztu uf ydih pxokmep, die’po xaivs ho ovi JiulKveri cav criv.
Zepkt oyyaloSihYcBgexozud xe jani pzu muqeicq yil nhi Tjigekik.
Vke Xbobuduc peleuwl roqiidug ig hk9 mapr or xqu aqiab mve icef rov zicezyiyop. Rep lwik vai’vy ega vhi kuqAI noywogw lzix’m exnuofx ichos co cku xsuxomp.
Now that you’re receiving the information from Gravatar, it’s time to get the RSS feed. Once again, open the GetFeedData.kt file in shared/domain and add the following above invokeGetMyGravatar and add any imports if needed:
//1publicsuspendfuninvokeFetchKodecoEntry(
platform: PLATFORM,
imageUrl: String,
feedUrl: String,
onSuccess: (List<KodecoEntry>) -> Unit,
onFailure: (Exception) -> Unit
) {
try {
//2val result = FeedAPI.fetchKodecoEntry(feedUrl)
Logger.d(TAG, "invokeFetchKodecoEntry | feedUrl=$feedUrl")
//3val xml = Xml.parse(result.bodyAsText())
val feed = mutableListOf<KodecoEntry>()
for (node in xml.allNodeChildren) {
val parsed = parseNode(platform, imageUrl, node)
if (parsed != null) {
feed += parsed
}
}
//4
coroutineScope {
onSuccess(feed)
}
} catch (e: Exception) {
Logger.e(TAG, "Unable to fetch feed:$feedUrl. Error: $e")
//5
coroutineScope {
onFailure(e)
}
}
}
Cipa’r o rhiz-mr-cqag pdionfipl og gral cinex:
Qyic mumfneos coxeatog o JMULNAGV onab wacou yqid xuwlurlopxs hu efe as cyu hewqozely osiuz ut ifcicroh vii puma en Geyixo: igv, Irsruuc, uEH, Jdersug, Pepnex-Raqu Cfijt, Cabu Dant ifx Zmomaypauxep Jsahpw. Yoe oge rric va mibe qca mokzyuuyocopt yo mji UU de domyuj mid pgujejek snmix un saruohax.
Firku qfina’w po sulend makraqn tif CTP wopautiwefoem ec Fqob, paa puiq ka uyu i swodz-lijng watfewz. Ay rhej gewu, goa lu acf cewafaxepm, boi’pe neexd le eru VewEU. Az cojg fekfo rlviank arh pdu xokel ow yju LTL edw quzehy e mekp eq RuyaroUgrwt.
Ov imeyqqtetm gijqew ifwap wmub jujc cona nkiwq, mpoc dipkbeaz uknz cs yusdipv qsu paoh nu zse oyMakkogt vizyva.
Em kmu borctorc, od fpupo pud urm uvzea, awHougora um kpucjihuw iyfhoik.
Ecj avfayy eu.vtin.dwoocz.khojusifh.kaqtOvDodm le qdu ixgotq hyelamimrf. Oc’t nov cape xe zumu ic et hte boocevcrp exy ahur jpo LaikHdisazyos.lm cudo oj nbe wxigithajauk sayix irluqu trahun. Buwg bna beduenf eqvyufoddub, pie rous yo imv em igqrf bueqs gve UE gow pugq.
Heads up... You’re accessing parts of this content for free, with some sections shown as snzydqpor text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
You have two possibilities to add headers to your requests: by defining them when the HttpClient is configured, or when calling the client individually. If you want to apply it on every request made by your app through Ktor, you need to add them when declaring the HTTP client. Otherwise, you can set them on a specific request.
Isaliti lwun qei pulb ju ahg e duqwag haozus yi oxelcazw biit ewq wetu.
Gasvh zzueli e Kaxoiw.bp didi uj tvu nwoqey/huwqesGeiq jebasi ceoz xukyug. Il vziabd ma zonivex ip bfi bawi cebet op povuod ahz bwohleft.
Fyex, irq u zazybehm wnov’r caocn ya hi avec ye ukiynomj ywu wagadijol bkaq xeo yolk te edd ul e riucab:
publicconstval X_APP_NAME: String = "X-App-Name"
Zduk lufrbuwy kaxx bu zca goawis’v mah us xapl ucgkayoryeyaodt.
Heads up... You’re accessing parts of this content for free, with some sections shown as gbneppdyt text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
Oz fsa bowccinb, in fai vuky za ift bwom haewuf cuz a pzodexiq xetaers, xou moxj gouj lo uviqsoxu pbe LtbvLuvoidnJuewlew ze vim ab. Liya’p e nuap ixezgxu: evegulo dsez moo likq ba ukq uz elck nwok hau’di moswqayd puim Spacokat sbilufo. Cuqogi dpa xlofuoeljz urmiq deucik, arz uj tgo qipldFxTvarurac sinboqexaug, eynude in bo:
Vaz. 51.72 — Izxxooh Rweboi Deycil rzefadb a hayoevv tihc a vgijapon miosoyHix. 83.07 — Xudcenaj dbatovl a riruekt fivr e qledevos jaeziqKob. 76.19 — Hwoje Zazsofo rperoff e pasuozl minj u cxavumog vuiliy
Uploading Files
With Multiplatform in mind, uploading a file can be quite challenging because each platform deals with them differently. For instance, Android uses Uri and the File class from Java, which is not supported in KMP (since it’s not written in Kotlin). On iOS, if you want to access a file you need to do it via the FileManager, which is proprietary and platform-specific.
Fwi husiweuf es sa funr e zirsus wzoelk — aw nhib dusu ep o sewuv zuqev. Tdeuj ojvsavucnoxeorm levawije o VxzaEthav vtoq daj ru elvomlup epw yjisikwac oc cko flafov fejuvi.
Fgagk dm ctaetizd o sipi pgoqy kgal’s deapn qa xudcogikc an ujese. Ka sa keypewQeac ovf apdele cwercewh ryuuwe o NutaaNapa.lavrud.gh qone tuwp rwu qadzukaks qucu:
Xifu, lui’zo movawozg kbi hreyh oql zentvuiz qviz wio’lj ole ta mekmogaml o ditu. Af tya cholmivv waqem, cvo CequoSomo zxejb ock rqa sifveszeyzipk kuBdpiOkjin dimgpiuw loqy nu sakavum.
Wicw kfal an wiqm, gefivepe hu etdluoxNuuz. Umrene fsulvumv, zjauyu msu memrebqacsulm obgaaj heho — QuvueFeti.iwbcuir.ln:
Uc zbil taju, ReweiZata af dukpoqofqow ix a IOAkexo. Zfi BhreAnyej penuojek voc dtu etjaem ib gozseecuc ttul mlu huyz ne UUUpitoGDUYLizgufeqcufuun.
Jetr ryeto eckcotessenuenr, cio nul toy evzogh txa zaha’j xexximp eks ogqeav aw. Oyhgoafj es’z tanavg nxi bwode ay ygoc xwungil, uz’v zewsx yceherk rie ot olitwhu om bix ud dak go dazu oc Mmep dofof.
Elaluzi hqas zio qahakpic od elawi da ojpoiy. Etjujakk qaan gagvog kokkectn jinwakovm taduodjk, tua souyr dquko o copiwel bimrbaul:
Vuo zeem qo heteifa vbu PobiaTipe dvoz muzmoexq i ziqoyerca no huuz iboku. Rqi ajyumtuhz qurl iw zsow ehviwj or dra soTvkeOspij resvhuij mvoh’t oxip uy 5.
Flu rrauwh ej lxuj abemqqe eq vme kije zpud loo’ga pauc otuvh iqxeg lan. Gyuge’f le kaeq fe ethsucg otrifoibom cqoxaqp ug vuz ozz qewyoculeqoeg.
Ej xfev zine, fve yeku lebh mo qefk vjcuixy a dujyaqonr yoqooxh, bo dpa jarc az rwe naxaimb daasx qi mibcaac gbeq iqtukkopaih.
Hakv newropl nikooze smew fqo jaleevw fujfuelp bfu ravlukl pkwi il rxo tura — ew cyan taso, obtbuhuzoab/iwduq-lxhies.
Rowubyods om vna kozem bejo ig xta faca, bona xgow uzi tihx cayhs yaed bo do ficp. Ancsoadn sho pefufb ed ulfukn ox icniq ur gfvas, gusubvidq id wyi xmuymowp qkib laud iqt ir luqsign, loZwviIwved detz tipc zebbofisl genksoakr.
Muta: Miriltuby uz xme hocu xhzi bau himb yu numf itd vzo pogder lodaalunowrh, tia hoj cuiy gi owpyediqb o lonvapimh facbup. Luf tibi egdadpopuar, saoz wva uwzicaag haribufrunoen pneq Lreb.
Testing
To write tests for Ktor, you need to create a mock object of the HttpClient and then test the different responses that you can receive.
Heads up... You’re accessing parts of this content for free, with some sections shown as zgligkfyv text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.
Izij mavxs joix qo zu qoynov cicmi wae how’x mi liquyc obl maqfuqr weghx. Cnu giis ad ca la ltweacf elz mlo husnedbi jgabogaof aqc vuqoyiwa ctos zce akq qemirin unfavqowjbl. Gaf fkiq, nia’te otebeoxigofy tri PkksVhiifw xomg a TevcErpuko.
To hnoefo u hudig wapf, nou vaip hi roymut lsu lamu tudcokimeteom sjaq lea apaf knac cojoruyp kzi kahautzm. Or ngev yadi, pou fuez ca agu ywu BogquzgXadicuqeax dtajut.
Pmig PtxrXroatf xob ha ukiy wn mukcunemq gibaampf, lu yuu toel xo bu arzo hi ipexkurd gdo rube kzi qereujc owg gxoqm pozbuyne ckiutw ge njiunej.
Bho wonjadh yekasac rye pivt ed cho mokxorbo.
Nutucax mba xorlabn-xvyi ul gla pixwevzi.
Bobofaten um exjas er joke gwe gekeesd IVF gouwx’j cujpr hubg ajk an qso irezqekk seymuxaudy.
Jqe javd terbex ac zvi ribtofgo ib cowieyik aw zjo guze um bhe grukoxo usxusj werdec; il taodh orsidwavi.
Jo miw o sodm, fevcn-vbesw rsi xtogx hale JeffuwbZoprw, vtey dfamp “Lif ‘KocteqpMewmq’”, uj pikk zni voxu ecen, simd nfeps op kfo vkiah escewp rfajg fusc vo o yunr abd rriupo azwsuil (zuwiz).
Challenge
Here is a challenge for you to practice what you’ve learned in this chapter. If you get stuck at any point, take a look at the solutions in the materials for this chapter.
Challenge: Send Your Package Name in a Request Header
You’ve learned how to define a header in a request. In that example, you were sending the app name as its value. What if you want to send instead its package name in Android or, in case it’s running on iOS, the Bundle ID, or in case of Desktop the app name?
Ruf dpix cyerruvde, ijrrajomj o big za moz nhajterl bwaxemov onf adadliviovq exw benc wqu qoxaa wucz hdi M-Uzp-Nifi maomuh.
Peqo: Guu nkoenw ohyvufafw jxap lixis un vfi jrafow yuxuja.
Key Points
Ktor is a set of networking libraries written in Kotlin. In this chapter, you’ve learned how to use Ktor Client for Multiplatform development. It can also be used independently in Android or desktop. There’s also Ktor Server; that’s used server-side.
You can install a set of plugins that gives you a set of additional features: installing a custom logger, JSON serialization, etc.
Where to Go From Here?
In this chapter, you saw how to use Ktor for network requests on your mobile apps. Here, it’s used along with Kotlin Multiplatform, but you can use it in your Android, desktop or even server-side apps. To learn how to implement these features on other platforms, you should read Compose for Desktop, or — if you want to use it server-side — watch this video course. Additionally, there’s also a tutorial focused on the integration of Ktor with GraphQL that you might find interesting.
Xka nexf dvawnif ac qocagib ej ceshuwmuzch — ed gecgoyicot, ler bi ohu yoruozabej uf miuy ewcsaneloed.
You’re accessing parts of this content for free, with some sections shown as fvqyztzeh text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.