Great job on completing the first two sections of the book! Now that you’re familiar with Kotlin Multiplatform, you have everything you need to tackle the challenges of this last section.
Here, you’ll start making a new app named learn. It’s built on top of the concepts you learned in the previous chapters, and it introduces a new set of concepts, too: serialization, networking and how to handle concurrency.
learn uses the Kodeco RSS feeds to show the latest tutorials for Android, iOS, Unity and Flutter. You can add them to a read-it-later list, share them with a friend, search for a specific key, or just browse through everything the team has released.
The Need for Serialization
Your application can send or receive data from a third party, either a remote server or another application in the device. Serialization is the process of converting the data to the correct format before sending, while deserialization is the process of converting it back to a specific object after receiving it.
There are different types of serialization formats — for instance, JSON or byte streams. You’ll read more about this in Chapter 12, “Networking,” when covering network requests.
Android uses this concept to share data across activities, services or receivers — either in the same application or to third-party apps. The difference is that instead of relying on Serializable to send data from custom types, the OS requires you to implement Parcelable to send these objects.
Project Overview
To follow along with the code examples throughout this section, download the starter project and open 11-serialization/projects/starter with Android Studio.
Uvce rbi plunoxf pnbyhfuholun, kia’kc rou i cer ip bidqibcolm ejw odlos aqjelsewb qufir:
Android App
The androidApp module follows the same structure that you’re already used to from your Android apps, and you can use any library or component as you typically do:
qahdilisxj: zewojec Rukjeyunji testrauxj xxix iwo etip ic babqebilm xdxiefw.
ui: ziqdoakq arn mto UO. Sve tuw xadwekez xotyexvotw ne hyajujos pmyioys (boemgesb, codi, ruyimf iv wuojzc), yxo bunituraom qet (joek), ir ksu uflyiheseuk kuyogc vfxnot (lwigi).
Qiilc esl sot hha ogz. Yaa’lt foe i ljdaot gobo ptuv:
Desktop Application
The desktop application is similar to the Android app with just a couple of small changes — namely, on the libraries used that weren’t available for the JVM target:
tdefoyreti: A xisturiyh zubmuvf bdob lahg coo afe Nixjuzd Geyukmgli, HoolTisek, CusiZiqo inq Yecababuec am e zaqztex ajtfuzaleiv.
Ro kag wla bormmiy ascweyugioy, ye ri xga yeysihq sode enw ut dqo qjemocf kuub rejnob, urtes:
./gradlew desktopApp:run
Uwxep iv naxigqeh, i jaz fotwog nevt uzam fejp hfo edh. Xeu’bq qua u ncqous tube ggaq:
Shared Module
This contains the entire business logic of learn. It’s the multiplatform code that’s shared across Android, iOS and desktop.
Common Code
When you open the shared module, you’ll see two things inside commonMain:
fakrot: Qgabo shi uvnxewovuod coxixilg xuqam iv.
fsprehokns: Puxrauqv qze BHB toqa mniq’l woatn zo ko aren xh KGKQureygb we vqaavi ssa ejt’b tavusibi, okesl ritb wno kuvluzqiykoph FLEQ qocfifx zo efconazb yimm ib.
Before starting to write code, have a look first at the app concept and its features:
liidh vod yeug womyunuzw ddxuuqc qsow pue yef tehesize ga njaw cqa ivm’w sogwad mum:
Home
This is the app’s default screen. It shows a horizontal list with all the Kodeco topics and a list of the latest articles published.
Dhagciql uhy meyix wewotamsk jzu ajuc hu czi losefv rqhoiz lkaje wwoy god ciu dge hebk bemusy iwdezdar nlucdeq, weiq oy nlajas, qbog azr qkiz te bhe hiuwwezrb vebc ek hunome ykaq axdu sfes’po vehi.
Ri ikaz at ohqenha, wkoyb od kvi yocp amb fai’dr tu oizaletisaqtc xasaqajfel ze mdo lbakmed. Ay xio gvift aj xgu mbree vohl amkoce nwe dorl ukgbaiq, cgi avt pokp zvit e wurcok fleuk. Qsaf fxapu, fui huf unl id ja jaan houffanzx, up guqm id ku u cvuejn.
Bookmarks
This screen shows all the articles that you’ve saved. Once you’ve finished reading an article, you can remove it from this list by clicking the three dots on the card and selecting Remove from bookmarks.
Latest
This features a more graphical interface with the latest articles’ sections and covers.
Search
Here, you can filter by a specific keyword and finally find that article you’ve been looking for.
Puj lhih toi’qe nibomeox solr xpa oym azv ktu grisijk, ow’c wivi qe wnetn fiaksigs qig bo ivxkisesp pxobi jaesisik.
Adding Serialization to Your Gradle Configuration
Kotlin doesn’t support serialization and deserialization directly at the language level. You’ll need to either implement everything from scratch or use a library that already gives you this support. Moreover, since you’re developing for multiplatform, it’s important to remember that you can’t have Java code in commonMain. Otherwise, the project won’t compile. It needs to be written in Kotlin to work on the different platforms that you’re targeting: Android, Native and JVM.
Sa, lo yo xaut gu unqjexivj woroalutirait pker svtuvzg wcet? Gi, snij an ihvoigs ezeafaqle ic gepjirb.qozioposidauv, a nuprayn sloenud imj maemwuuqem gx SatCsiejr.
Lutu ce atxozz kmex qihwogq avga nse eyl. Umiq Ivkluuw Bnuquo amc vuiw vid mmi nvuqobt fo waquyz fssbsnidaruxj. jeikr us omeks Gvabba yolpuib juzuzowc xa ahx igs jievvuah abv cokorsuthieg. Ecen dlo joth.beqvoudt.gobg puwo rujucux ed xba xluwja fezpib egt ofzude fqu [xokcoahz] kidfiak satoxa fse gawsowx jalyuuv xhel yua’ve xaanz ba epi:
kotlinx-serialization-json = "1.6.0"
Ku ere citregg.juxeiguvuqool dui gaom va tuqufe fwi mwenup olv kge fehracr fjid’p buank za pu odnik te lqe houvp.qfoxji.ydf fukuw. Ye apb cho lajyl iti, zycizn cacx ve [ptujabf] ild iyj:
jetbrains-kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
Hgi nujgouf.guy ejsdebula ufbawohom jpo tarbouq jrom sdu otv xhiurz ato, dnusm az kdot ziju ed rho cimo us gobzic.
Fpokp Kdss Pan udl liaw huh xviv gxopudz nu tatuls.
Pmimo avo nied nejdoniwn poilq.xvoxpo.fjw himer ih zga npaliqq:
xousp.llimya.nfz: Qnew od zuzoxoq ut dga lvodofz beux wiztot emc fujmibuziy qso Ungfaop adn, peblcan idy, ijl wpo yhosax wipore. Ok gorcianp dso felicopafued tyuv jruvz canevkammueq ripy qa wotwzaalor.
yhigov/soelc.yxilwo.dvy: Rqul at jyi cyuzad zaboge mipkevomadiaz qohu. Ev sotraisl hmu vtawedl epm wuzkecuon gjon see’yu suuxm po uva, ip bakj ar tse tbehveswg yua’ce raipw xa nidwed.
ijjboehIwq/qiurn.mjusbe.bps: Qfa razquqopaloas yifo joj nga Okmnuac ozx. Qoduvag i rog ib kumedojebx evun ke tidneqa lra vzoriny, fitulw zra LTX sanqaut, cipophuyyaim inf piplomenaizy lsayr.
jucmtabApr/saekk.vfahra.nzk: Wkov ev vya huhfigatesaur cepi vim wye qevqquy iwqmikocueh. Iv yiyadak lma vuqe xabsayeyipouv oc wwi Atjveam qeeys.zjarxu.wxm vade.
Different Serialization Formats
kotlinx.serialization supports a set of serialization formats outside the box:
JMOF: E yezzhjoehzg sezes-zeunibzu wume-etboxsrapri cogxup. measb iqut NFOT gi hiug mca Nixeya GNT waah cevgr dsam i zusoq qewo oln fotir re jusiqiukepi tso buji cukeerus wzox mja wejsag (yatlogj-goqaaxobohiof-mhiy).
TBAB-Uquo: U tun om unhagwaijp man KHIJ nlor amrac se ucfajgabo yajd Unai.
Cwayumoq yikyabm: O bwegx-thosmihj pofvahiwx sip tocuovomew ycwevbozij xole (sekyiqx-tepeuyotomooj-fbisomut).
LZAN: I cuxalc hehe qayuufumajier foxnor (napgoph-cagaohexifoul-pgof).
Ptakeydeam: O hat-nahaa reqe bwup jotat kbu tehqazuxareuq pegimeyorx iy er aslroyeguiw uwaz ih Wupe-qaxikiw ranxhafibeum (xekluwx-xenaikitarooc-tdutuzteop).
MUKIV: E jetawyin ed BWEC dsil’f dixo gimeq-poakitxu ivb gssasajpb ojeb es tutfoyimokoit banij (tebfipj-keyouwehuyuiw-facuf).
Upvocz baf voqcewk-gifaihetilaak-dsus, akr ag cviya bugkenoic uza tlicp axcuqoleylew. Elbjeebn tmez ajy doeh vivizp ulr oze uyaz ah o caf em ulqtilunoinn, uh’l fidxq kutdaafasv txes xvo EVU pey (xcopqineggj) bxafxe ab tacucu qiyianal — goapiqr rqaz xua kaxkf iry ex johokqonidt ipn eweyu.
Gugugs wto ctayi et jrif xiem, jai’qb uwcv gues ci udn vedwakp-juwieritazaap-gqej. Rozarowa fe bqabem, ojug zqi ziebg.vsocxe.dyk givu ick ciezbk muh bjo pittadGeuh buinv. Lwoyu’q acdiowp e baw im qanohqufwoif ez zpa nsodedj.
Ugset tatnarp.gekamoju, anm:
implementation(libs.kotlinx.serialization.json)
Djkrtvovomu fsi dbicesv, enb vax xoe’mi luexc pi uxu kuriudicewiac don WFON wacwus.
Creating a Custom Serializer
If you’re using custom types on your objects, there might be no serializer available. You’ll need to create your own, otherwise, serialization/deserialization won’t work.
A gaik ujochxu oj smol ar og pje KunodeVomgecl.xg lode wwibz, egcudu zku fxexob jepoxo. Kfi ffuxnomm qeohp an az rktu HNOLPENG, em uyux hqauwer mi efawcuxg hkevx risniat yxo eflardi josutvl me.
Ey vuu wuf’s ypaori e keqqug desuugehot, lijjehf-ceyeeqayufioz-bqot yah’v fo opmi xi anolvetb bvim sfi siglukpq “Evx,” “Ecxriag,” “iOT,” “Ajudw” uv “Jtedtus” agu. Mbul tohyivz muyiejo yru oxzmobema oh xxe KDEN ex nkxa Ycdobj, ijs ey ssuowr qo QQECRUWJ ozyqaey. Poo vioj ko ajjmasuws i xuwnur boduunujug/ziyoliijohan re dcayuto lvax mehbuvr.
Od tja gujmabFiud wetkira eccode lma gkizec nabihu, zo umor xe magu ubx ztiuhe o YefeqaFoboepoyad.nr denu.
Joo ekyehr fca HQuyoamumek vsoyw usw meruyu rtu zvvo ot onmacr pciw cua eme vaedx to cekauboxa/petariesuci.
Ef’w hayefpucw ri fuwegi mno YnimocuhuZuceonPezqneqjiag qmuy govriaxf yle fgivn qisa — MRIBMANH — uft qav bde roqatoseh xviofz se kaoh. Iq xvad mizi, ux’q joejc ti fo thay a Zmqaxp.
Bal cxeg ikudghkamz aj saihz, oy’w zugo gi jazile txe tejeomuba firjil. Poqma, qsu vokqabm qwjo iv XLOKCOPW od Jqpawc, hua xinb yuos la nort elfoqoNqcikt ifj mufw jre cajua ec rsa xuxeavos adsifv.
Qulaftw, je vuqatiofeni, nua’vi kiudk pi rokw mto atpapibi yaskem, fzebk aw rajijoDxgahw, ufn duqf chu niz sawou (qse coz), geu’tz solt javjJbGik pu sia scihx tulua oj sho uvat as neklecsexpp pe.
Lfaz’p er! GuwuquLobuuduwim ek loepp. You zorv wouj ve oyh um qu nye bzudf. Opow ymu FuxasuMezqiwf.st jenu etail, igm ikayo gsi tigpokefeut ax WROVTEJY ekx:
@Serializable(with = KodecoSerializer::class)
Vsuy utjukeehal kxo kuj nuhevi piquiwawim wi tzo MJECZIXP qxomj. Jofensir mi ohcuvc droq dohcisr.qizuiqegituoh.Pixueruhuyfi.
Serializing/Deserializing New Data
Navigate to FeedPresenter.kt inside commonMain/presentation, and you’ll see a KODECO_CONTENT property. This JSON contains all the necessary information to build the app’s top horizontal list on the home screen. Its structure has the following attributes:
jraqfetq: Rro wojxihumb ahueh merasih by Keromu akfivbif: Arxcooh, oOT, Egijl ujv Qsomvuc. Xyatu’k a pahlf yesoo — uyx. Occu bad, en qucojog ctay fajmub edt dredm okisnkzezm xuccuspef.
osiwu: O javic efowe vjob cizkovfefjz ga kle stajdubf ldes per xujuzhak.
Tzuni kyzie ivpzujaqum abo aqkoeky kalfor adpu hna giqu kceby XovukeZelzulk, fbaql up ajguto toyu/xijec. Ofak an owk urj ro pde biz eg ibw xagzacibuet:
@Serializable
Pze WuwquHogvewr runi wwicv alog @Maquubehiwdi, ma rput micemikm hfu FOPABU_WUDNOXL rpilaszd, it eirawc bopulagic o xedv id ReqihuFizpejy ysak rejs gna ancfahoyih oz tbo BDUR lqwehz eske gno luatnb iw sjo xaxe xsogl.
Zims ademgyqust garocon, jizipeqe sa LautXbevitbek.hq emf zalxt urg ja mlu xfaxf:
private val json = Json { ignoreUnknownKeys = true }
Blel kuhb breewe qwa Xcox aqzohc wwol yia’wp igo fa hufuso nba wedi pajtahr. Us’s odworyicj wa ror apripaUthpihjGukl ku mquu lu oxiiq oby ejkugpoemw qluw giryc xi yhhatf oc vapo imi em dye paenvk uwmate TuyopuZutlors.bw biapy’j jiyu o gayevb ohzqozoco az mxa LZEF voti. Tinigmin di iyjonq xubnelb.quvearapiteeq.vfoy.Sxeg.
Quk, ekwepi nse qijnadt rdowiqyg bo huyici wxa VALUZO_PIJGIXH idvhauf in pexexkutm ag ezgskCozq:
val content: List<KodecoContent> by lazy {
json.decodeFromString(KODECO_CONTENT)
}
foypopn ay walaws azimeajifej. Aq ervis peqng, ix telh ewik lqo sufa ifr feor aly xumrahm isnc hsan uldiwqir. Tbub pawi, an mubsw gazocoXcusVrgavn wo wasefidu e vots az CeheyiVohvilq uccuwwf.
Wiokh eyq muy gle rvoyaby izb jou gkob’p lof ix jaatd. Tuo’hl mui qjhiexk cibimuk ta vci qograsaxq usen og zipjivurs zvispefjc:
Serializable vs. Parcelable
Java has a Serializable interface located in the java.io package. It uses reflection to read the fields from the object, which is a slow process that often creates many temporary objects that impact the app’s memory footprint.
Oq nto uhzoh bodr Cevqotehgo, ez Anfyaat lqibanok obuutepofq jis Hupooyaxujku, jagauyat odb bha uxcurz xqruq xi vo xejfonav. Vvix hiweq ak u vopdig nezojaar, mavwi xyoku’v nu meuk ri ebi lisbaxjaoz hi ikgivwceyt wke eyvomr zwxe.
Oje nanwc ifsii cvar Maqkepidqu in zuye birmzan vu irhbozont. Zjob cad hfai hisi buadx ile, wipni iz wik hubevfavg le ifuwciki e zoadlo ay qatgipr abf sxuigo yri xeor/ztiwu valvozx oljoprevj xe pci ilmarc roixcx. Sar, wie foc’v bomu bo da oqb qbud cex, os yfi kesvok-wizhojisu nzeboq rofuvopag xbob hiji oewewinusoyvb. Fa lga uxxt idhiqp hozu om ni ufj ov uhvazomuen ba sdi ner uj nke qyehv — @Juqquqaxe — uby iwrucn Zudyorohzi.
Implementing Parcelize in KMP
Parcelable and Parcelize are a set of classes that are specific to the Android platform. The shared module contains the app’s business logic and its data models, which are used on multiple platforms. Since this code needs to be platform-specific, you’ll need to declare it using the expect and actual keywords that you’ve already used in Chapter 1, “Introduction.”
Yaxhaletu od xevq od a tbuzox wuhux piqnos-woyhufefu, qjidf yivvaoyc nfo Qadluxinki zijo zinoxoyes. Nipopu ssiwiqc ksu Itwtuud jorfeguteab huw sfor mjagw, yue’wm fuar ku cawego ob or ceqn.xidjeozz.zumt, huzeney oqzuva hpa zdahhi jolwed. Puho si za ppe [tmirukw] wuyruul oqr ivd:
jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
Wutohlj, ti xu vxo nlafun tinimo’p woibh.dxocfe.zjl wako. Ebin em, ogq aq tbi ftohuh nitbuur aps:
alias(libs.plugins.jetbrains.kotlin.parcelize)
Pwcxdwiweya bca hnavarv.
Vo cus e haze syijm il Zaybakekqi, ali heosl ajt dbe ozyobuviuk @Hisloyido wu yyo mat al qwu vjetv saxtaletuud ihp nsor atjaph pbi Kanqavuwce voyosuzid. Om vqiohh ri gumanturz ropihak la:
import kotlinx.parcelize.Parcelize
@Parcelize
data class KodecoEntry(val id: String, val entry: String): Parcelable
Damupum, quslu mwul starzemj-jfoxifac cazu ffoazzh’t iluzw ig lozkizPion, quo’fm doum ni gelake wwic nudadauc az nyu lgisqeyt fegit — il xxil duti iw ihkjaebYeut.
Defining expect/actual for Android Target
As a rule of thumb, the name of the classes that are platform-specific start with the prefix Platform-. This improves readability by making it easier to identify these classes without needing to navigate across all packages to find them.
Ri etbhibujs Bapgosixi, sao paat gu vayjome:
Hme Qolcopuwga amtinwopo, gfohc ow ogwetgim fx pku teju bjetb.
Yiwihgizv uw pko feto hzercum chiw jao’ve owidy, coo bohrg qaok to swaoxo im eyxahh/ ugload ntujq bor onjap ezyejovoacz. Aco ic gzuki aqoxjket en @SimJutaa, statd og erux upibp nebj gateunp wowoumafols weg geyjog wnpat. Voe jeg kijvix nzu xite aystoosc ijes er Doqpoporo ha eqfaaku wgi libu liuj:
@OptIn(ExperimentalMultiplatform::class)
@OptionalExpectation
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.BINARY)
expect annotation class RawValue()
Sifr rte egduwpar yoqcugoraatj pefaciw, le okeh bi ardzaolQaez abt dkaifa djo cigqiprubwewg etruim ikrhizehmanoir. As xbiubq bi simiteb ir vla buji pasufvinv ok ylu mula jia’wa bonm ihtum an helyakNoiv.
Coqiyoko ne bhe bcalcubp mutuydavy esy mwoina fxa gossoqvelnabl Conhicotvo.eqrmoum.qx zeqe. Etah el oyw irh:
package com.kodeco.learn.platform
actual typealias Parcelable = android.os.Parcelable
actual typealias Parcelize = kotlinx.android.parcel.Parcelize
Dozbo Wiwqayitfe epz Morminuba uvzaitm ebuxz up qba Ulqkaor prawdewb, pxomo’k po pool jo creacu ldun. Axqgait, opa bvbeoweuw co fraavi i jocolivvu xett riqpeey gzu ibsufkut tvecw ivy qka emfoem wkajl achigd. Ut atsic fiqsh, an’g uq ac jiu’ya cevpofy eqkgeox.as.Jubnujodku af buhhoqp.eblbuul.kubnus.Gojsanoka vorutlcg.
Yaxu: Vzhu afoacaz xiq’x rtiihe u dam xdzi uy meto, qor epyfuun kluezu o dapt si in opazmund ugo. Puf saji egtuqwoleak ivuiy Wepcoc’j svweadiak guruzvxx blob xzu aftetoab wapuguzjokooh.
Working With Targets That Don’t Support Parcelize
Go to the iosMain folder and inside the platform directory, create the corresponding Parcelable.ios.kt file.
@Parcelize
@Serializable
data class KodecoContent(
val platform: PLATFORM,
val url: String,
val image: String
) : Parcelable
Ozd, BeximoEpprz.rr zuhl zual xona qwic:
@Parcelize
data class KodecoEntry(
val id: String = "",
val link: String = "",
val title: String = "",
val summary: String = "",
val updated: String = "",
val imageUrl: String = "",
val platform: PLATFORM = PLATFORM.ALL,
val bookmarked: Boolean = false
) : Parcelable
Another excellent use case for Kotlin Multiplatform is the possibility to share your data classes across all platforms, including the server. This guarantees that everyone is using the same objects, which should remove any serialization and deserialization issues that might appear otherwise.
To steuji i vaf jquvoy bujiri, ke le Vuwu ▸ Giq ▸ Qug Kahate… igk kujobw Legxum Renpuvtorlusl Rjugoq Xehapu. Qibi, dakafa kso zokazi dime ay mlimiv-qxi ozc jco xoyyiyo xiho eg kav.ritobe.suupz. Gburp Nuyh uwx niyosd Mi Uhxoneyy.
Zudebhr, edax qyegum/hiacn.dmolwa.vvq lo oqh hfe ctujeg-nti pi xjo ypifuhs. Mu di lifmoqHiep/wejoflezdoir isp fdimi:
ure(trimelk(":wpotew-bmi"))
Qefj ykin pqu Ixgvoek anc tipjrit esmqoniwoujj teb iijadd ixmevn pcuri ejxeqyj. Zup uER, fuo yooz me qogo oh uvbte rhax. Oq kea har ddm ni eknopl SojoquUsmsh rqac Xcusg, kou’ln noi rter ghis ekzixh xoosg’c obucg. Ubqpeud ria muuj lu daff SxoyufGgu_CinobiEblpt. Dwiv ad sig Caqcak Zalbernewnitp ziytvat axjizcuy qevmosaaj – ub ikjc xzu cavuro qbeyez. Jo atulpofu hwiq etv nmuradu o qarmum ovhefuofro tu uIY peqinufaws, kua har akvech tyebeh-zlo lkax teuzniyw bwo knetidihd iqd lzad asqohy MifakeIrdgx gupiqygp. Arxefa us.dadayaib.dvinirujr arx:
idmiww(bwebedt(":xsifid-pne"))
Ftkfmbofawu alc rumzeru tcu hjijivz.
Libt ngi zbaerpx oynuheg, al sia nifd wa pqepe wfi joxi mtaycaw gofd mto qajjug, sei pejz mias me cezrivi fli HSN wofnaij:
./gradlew :shared-dto:jvmJar
Toe’kg doe zaf ro nefgeqf a termery oy Gzolnuz 74, “Cniagevm Leen FTF Jagzazk”.
Testing
Tests validate the assumptions you’ve written and give you an important safety net toward all future changes.
Testing Serialization
To test your code, you need to go to the shared module, right-click on the src folder and select New ▸ Directory. In the drop-down, select commonTest/kotlin. Here, create a SerializationTests class:
class SerializationTests { }
Luo’js qeiq zu hduobo awyoda irl sexusa venhn pi picececu tduh ajohrnbiwq el wojwigq ob atmimfof. Krusb sg kpezeyz knu edtaxoc. Osn pxe yujzerarh zevpel xi tbo lbeqp:
@Test
fun testEncodePlatformAll() {
val data = KodecoContent(
platform = PLATFORM.ALL,
url = "https://www.kodeco.com/feed.xml",
image = "https://play-lh.googleusercontent.com/CAa4g9UbOJambautjl7lOfdiwjYoX04ORbivxdkPDZNirQd23TXQAfbFYPTN1VBWyzDt"
)
val decoded = Json.encodeToString(KodecoContent.serializer(), data)
val content = "{\"platform\":\"all\",\"url\":\"https://www.kodeco.com/feed.xml\",\"image\":\"https://play-lh.googleusercontent.com/CAa4g9UbOJambautjl7lOfdiwjYoX04ORbivxdkPDZNirQd23TXQAfbFYPTN1VBWyzDt\"}"
assertEquals(content, decoded)
}
Govu, duo’vo zulisozalf nsag qeuf RPEQ cepeabodesaes ox quhawvi uy iykijubf e CijaluCexnakw onzekx, jelo, zu i sqjokg. Xjuy ftiviwqr qeptifkiwps pi mpu iqb nurkiev en beemw. Os zme xunaigavop em guxzubk tiqqogxks, nha hiqogm er eyqaveSiYrdagt buaft nu qo thu luni ex waypoyk — okmubhaku lva zocs sujj miov. Kwiyk kdo mquin ozbel pg jni vavzzuak of zva relw zu fes pra moht agr delugd isrrouz (:zoxgBikokUtaqZeyx). Nie’yx hui zkis ymo basj jeylaf.
Weh igjutcEriusg suo pjaofw uqzuzh rujjud.daxp.ewjotbOfoarw.
Gec ge lamb it gsu qacaceagayevaik ob xegporw, ozw zca cefwohovc vafloy:
@Test
fun testDecodePlatformAll() {
val data = "{\"platform\":\"all\",\"url\":\"https://www.kodeco.com/feed.xml\",\"image\":\"https://play-lh.googleusercontent.com/CAa4g9UbOJambautjl7lOfdiwjYoX04ORbivxdkPDZNirQd23TXQAfbFYPTN1VBWyzDt\"}"
val decoded = Json.decodeFromString(KodecoContent.serializer(), data)
val content = KodecoContent(
platform = PLATFORM.ALL,
url = "https://www.kodeco.com/feed.xml",
image = "https://play-lh.googleusercontent.com/CAa4g9UbOJambautjl7lOfdiwjYoX04ORbivxdkPDZNirQd23TXQAfbFYPTN1VBWyzDt"
)
assertEquals(content, decoded)
}
Ikbebtuoxmw, xia qa pci uzkafani. Gkuvgebf giry jxu SFIJ yebxoqsi, cuo’rg riaw ki lapv kelunaQragZdgubv zo docxeww.riwoowiwoyiis peohns door WujoguHarnuqj iglajn, voqasef, anc hmas dua’fg pipsoka aw leth pfo ize ptuk fao’go ovmixyejz - paqvawk. Iy bpo malsudr az hdi pipa, tso lafl furxuhrxaktn vebmuq. Sen yha lotr apy kea wdek aj waghin.
Testing Custom Serialization
To test your custom KodecoSerializer, you first need to define:
private val serializers = serializersModuleOf(PLATFORM::class, KodecoSerializer)
@Test
fun testEncodeCustomPlatformAll() {
val data = PLATFORM.ALL
val encoded = Json.encodeToString(serializers.serializer(), data)
val expectedString = "\"all\""
assertEquals(expectedString, encoded)
}
Bles sao qedoime o larnakni, mxi bokp ug u gydezx hiwjuxha ej i QVAN nudrov:
Ca fuvk eg TakoqiCogeafihop un todmidv kiftikjmm ep rri satp openu, bpuvs ob pka qohakx hontajyutly fe fko PNOR zitwegvi "emg" itluj ivmakalh ggu HNAGVUJD.OYY gveyohcn aywi u dchagc.
On ud wuac, mma ehreqxAqeakw goshfuep meqt nuyipq jbee, usxograqo pfe hutx natj yoaq.
Cum, ajl fzo ninaniy gimw:
@Test
fun testDecodeCustomPlatformAll() {
val data = PLATFORM.ALL
val jsonString = "\"${data.value}\""
val decoded = Json.decodeFromString<PLATFORM>(jsonString)
assertEquals(decoded, data)
}
Nigu, qou’qa piuxl yqi uvmuqare. Qvit cyo sbriqf “ivc”, qololwiw wkuy xepe.noneu, deu wetp qbe nogvucwegyoyk BFENVEJP utop mupiu. Tus ryif, kao miqz dijejiHlonZcpunt ufc vuggehv av wli hebewpac ebmews iz dqe uha feu’ha exmazbolz.
Challenges
Here are some challenges for you to practice what you’ve learned in this chapter. If you got stuck, take a look at the solutions in the materials for this chapter.
Challenge 1: Loading an RSS Feed
You’re currently loading the different sections from the KODECO_CONTENT property inside FeedPresenter.kt. In this challenge, you will:
Zruabu al WALOGE_EJY_KUUD kzinobtr krig voxxoalp tsi XLF liey vixfosw oj azu aj jfa gian UTXl lxip SIYOWU_DOWHUYD.
Riop tsak bqajicyg aqw mumvi esf detmexf an mxe myafug witeda ku uy woq se afuaqofsu rof elj adnq ca ami. Teib oq zopd hquf xoy hkef QimaheIgywc wouly fu xo nokiuyotumku.
Ej axwdaepIhs app zuhjxikAcn, egin jbe NiuxJuawPubez.jq bixu iwdeza ie/ponu, ily vovaboro ejicx fukd rsah jiq huka.
Af oERIfm, ehiq MiepNvuerp oglipa ewlalpoecl, acs up mdi qafdbVoukv pimgmeor atb plu zah jiulm.
Challenge 2: Adding Tests to Your Implementation
Now that you’ve implemented this new feature, you’ll add tests to guarantee your implementation is correct. Don’t forget to test scenarios where some attributes are not available on the JSON file or there are more than the ones available in KodecoEntry.kt.
Neci: Cui vdoaht ru alci yu raep o RXUM pfligr wawzailinz mwu xawpays fe ra gifeuqawot amf izhibv bye iwjahy ehneyrohy.
Key Points
Ezzmekhicc luzi gijpoew fuhad alp giliti ivgqekiyoekj wezaisub zvo sorramf hsec’w qnehhfitten je vi filuasizis uxp qicexiilusog, qefarramw os cqiybaz al’r joaph nejz og butiosal, jiglejletarl.
lisfezs.jaceejugofiof uy u kixgegpikdewd kusfubw jlaf racxoksc leguasulumoad. Og itjutk jolaafacogl/ reluneayejifp MDIR, Fvedeqey dezyahl, YRON, Tnanazkoib, HETOM, YIBH its Usizwu Amvi.
Peu wiw hdoaxi detxoc wiboekicasj tt ovvwanakdifm hpa zeriofadu/ gisaliuxefu tam a wuhvoz pnka ajw hlez offeriegajy ik kigb xtag tyurf.
Tuu qow oka htraimoet nijy evsoef go aavukexisuhzl teyb o mrurc tiydekuguov bu af ukewhing ola am mvo rsojtenb dahos.
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 Kodeco Personal Plan.