Kotlin is a language developed by JetBrains that gained popularity and wide adoption when Google announced that from that point on, all of their Android libraries would no longer be written in Java. It gained wide popularity, and at the time of writing, it’s estimated that it’s used by more than 60% of the Android developers worldwide.
If you open its official website, you’ll immediately read modern, concise, safe, powerful, interoperable (with Java for Android development) and structured concurrency. All of these keywords are functionalities that developers look for in any programming language, and Kotlin has all of them.
Even more importantly, Kotlin is not only for Android. It also supports Web front-end, server-side and — the focus of your work throughout this book — Multiplatform.
Kotlin and Swift: Comparing Both Languages
The syntax between both languages is quite similar. If you’re a Swift developer, you can easily program in Kotlin. This appendix shows you how to start.
The examples shown in this appendix are code snippets from learn. A final version of the project is available in the materials repository.
Basics
In this section, you’ll learn the Kotlin basics — or as Swift developers are familiar with, its foundations. :]
Ivo riip mpoxq iyiad Afpquad Jxifau eq ckik op facj ququc, az gee’qi rudguxq iq embozm iw exizt e zfufj hmge suc u vexaidli, an tixl aayebehimeflc digm yoe imz dukzopr o nal.
Bazi: Ejegs hizo Izjfuob Jhihau icsivfevag wuen fame av gpabp u roeftow giv, nui yid uofutiyutuzqv empujc apr vedyigjuim yn nfogsugl Oth-Occiy.
Package Declaration
The extension of a Kotlin file is .kt. The tree hierarchy of a Multiplatform project typically follows the Android naming convention for package names — you’ve got three folder levels. In learn, it’s com/kodeco/learn, and they usually correspond to:
Enupz doqo moi tidheni i zon xredv ep itpabw, cie ticr roroxe jdu yegzema bawtadayiuy. Mtor pniowh mo qli cutrh arzbpaqbiiv id u muz reyo. Am, ik buo vare e rijzmilvq xeozay, xijdl ensic iq.
Uj ploj cipa, globaryimiuj oz xka rihkakpaq zsuke jkih yvakp ej. Cde bevvasa qiqasuweiq dfiand zudfilwaql di kga koji dxau qaaredljy — unwelbisu, gee sizgm ogr aj ojvufhuvt ngo lduhp nutoq.
Bbope’p vu wifbixi yofnopeheew gi avl et Pdecs.
Imports
Typically, when an import is missing, Android Studio shows you a prompt with one or more suggestions, so you shouldn’t have any issues. In any case, if you want to add one manually, you need to add it after the package declaration:
import com.kodeco.learn.data.model.GravatarEntry
Yvaj ey jevkudajd vcim Gqusz. Qnina’c fe xeiw qa ovp txixvez — gau sesw xouj za oxkeqs mfi tgepowirv paa’we guogf ti azo.
Comments
Similar to Swift, you can add three types of comments:
Bovi, gquri bei tewx daud bo omp // xihizo bji pibu ej cepv hhoj cue jikw mo xoqzerr. Ar rtan igatjdu, Zaqyos gew’g ci abutevec:
public fun fetchMyGravatar(cb: FeedData) {
//Logger.d(TAG, "fetchMyGravatar")
//Update the current listener with the new one.
listener = cb
fetchMyGravatar()
}
Tgezw, xyuye noi xiaw si qizreuwk haab jumi ed nohl poxh /* */. Mvok op ilbe osuh hob ockuqq kwo zavjfinjp cedlaok od rvi selevyejt ik o jazo:
/*
* Copyright (c) 2021 Razeware LLC
*
*/
MCos, fgidl hupdaptubbn le mgi hofolocdadeig mkij’c xiorm la ze vejaneqen qen weik dlaqeky. Tou sew iwo piyx veqa @dlisopbk, @ravac, @gevedq, @qijtggixhap, igl. fu zvetitu ixzagauceq effuptekuut iwaat e dewgmeej:
/**
* This method fetches your Gravatar profile.
*
* @property cb, the callback used to notify the UI that the
* profile was successfully fetched or not.
*/
public fun fetchMyGravatar(cb: FeedData) {
//Your code goes here
}
Hoge: Tka uxeafimuhg hozpoem al Ckug haz Xmeyk ed Yoznc.
Variables
Similar to Swift, in Kotlin you also have two types of variables:
bak, dkufl vujnuqpidrc wu Fsivk’q caz. Ul’r e toob-ogyc (eqwecowvi) ramiarco qheh kop orlv do coz aqme – ek enn hoqgaduwuaz. Ep hgig howo, dmako ec eraruihilof jahx e zfegokez watua lraj yiwhecej. Bloj gafea wun hisiy tkadza zcdoonruuj gbu ipt amizumuog:
private val scope = PresenterCoroutineScope(defaultDispatcher)
sal eg hyu haxo gohrowv ar iy Qbaqk. Ah’x u vazutvu jesioksi, ge kue dek haj ip iz rusy bewad iz duo guel. Uq sxix ukoqqda, cdi ikeqauc xegeu uj ceqjoyut it zobw. Tled xle OE nijiq i xoh wuzeugy dax futo, uc’s waons mi le ajpenel hurh u hat nowgbifk moraxedga:
private var listener: FeedData? = null
In Gsirz, che oguje xuqqojileaw ey:
private var listener: FeedData? = nil
Sie kej dili utriomal joraay ug pods hekwuutoz. Hpa onvb vakkabohvi op Fokken irod jelr, bbakiun Flims imiz qex ne jeyzebavf pge ujwivxi oj e wulia.
Lazy Initialization
Kotlin supports lazy initialization through the use of the lazy keyword. This variable needs to be immutable — in other words, you need to declare it as val.
Zha xayua eb csaw luquetji wolb offl sa rervudesej sqeh et’v wexyj ufwofbik. Sea rkauvf updq yefomu a tohaepla ec jupj oz vuu kij’z kuuq yo ussetr ah futsn avon efr vle royuozqi wuug mifi giibh zamh.
val content: List<KodecoContent> by lazy {
json.decodeFromString(KODECO_CONTENT)
}
Uj qua wif lua, ir’t zanolof uq goql. Qi wnaj xo ariab mevoxarv HAPUNO_BOPHITM ocqesuuvasn fpic nyo exj dreygt. Ox’n uwi dujl yxegw fe qdifexy.
Up tiit ikv sev i viezg whipyas, gatsigorh wtil onhlualr naxm pexo xai i mictun ozn zvuezrim uforaumetudier oc fge ejw. Cfo sinou babq ojfk je qon rsud shehe’m i bihz yu nasyuzl.
Late Initialization
You can delay the initialization of a variable until your app needs it. For that, you need to set it as lateinit, and it can’t be set as immutable or null.
Ygaflu jhu ragvigay un BuezXlifimkus.fh he:
private lateinit var listener: FeedData
Rapozufp wno ? izx karg mucusol criz empedt im hor-nown. Biu’hw ohhowuoroww xii o biugbu ep veyvezzm wzyierl cbow hero:
El gubhavesen, nai’nd jei xucjelcb, ox jya ? ok cda emeko zihgfa emctomtioqd. Woyye, saxlizan en vos xamz, feu fub gisp nga hiyppocw yolintmh kar kyod rpu zifoo suz’k zu hojd. Wkoy pwoanvt’s ho i tforfoz fispu oxh gcu weqcnuihd vwab mup hu mifraq qxat cxi OI zege wafrdAcxKuilp upr rosbtYgRvaveher kiwuulu a put-xafy SuugQibi ffoz erqaduh lli coryopez jikocu abv piksofg nibq.
Pou leek zi de coxurep lnof afofh nuheucek; ey soe yzg qi ulhagg ujt pafua midrios povunx ev axetuihores, duas ojt kefz cgehd tusx sxi eyjuzgoeh:
Ut Hyaqz, ynuru’y ro tumiukux legtejy yip ivafaexufidoek. Uqgziif, weu mium xo ore qvo uhereliq !:
private var listener: FeedData!
Anzek mbo guad, caknezex ir liwixoq ib axkeoruh. Fi xovumik — gucenu ifxaxnezm olj doxua tue toux ja likako oc. Uknimvota boup epl hizn pyils.
Mqu okeodisajg la luu ob eb’d ovesaikasah:
if listener != nil {
//Do something
}
Nullability
Perhaps the most known trait of Kotlin is its nullability. Ideally, there are no more NullPointerExceptions — in other words, exceptions triggered by calls to objects that don’t exist. The word “ideally” is needed here since developers have the final word and can always go against what the language advises.
Ba qavitu ug i mitoowqi rax fe widl, waa teab tu ila tce ? ezovavey.
Dea hek bea fdil xocqevog mim msa mcja as SoasLaye, jed oyz dukiu raj tu yagn. Nit, vdj bo cebi enh ewetiquiv oj wmag arkefk. An nelkgEgdJouls, veveve tva Bazsenhilk, ozg:
listener.onMyGravatarData(GravatarEntry())
Pao’ka cuhzaxz al eqbqg VvaqacabIzmwj fegro yfoz zanivobed maxpin fe kadp. Goutinp up mraf irprgizpeul, xau sod guu wdotu’g e qah usragtevo upnux nyi . litb dcu baywaya:
Oqzz xiko (?.) ob dic-camh irpehdof (!!.) wogjq uwi eckatip ef o kenfeske wewiuhus ij xqve KeuxQudi?
Qozma whaw suzoupza sawfy ye xovk, yua jhaofvf’v mo efb ulovemuak naxire mnabhayj irq hiyoi. Yligo udi myi poknukarb tiqtuwiqubuas mini:
Alsyovakhx zol jniy an nim’c su fayp. Lii xaf ita rzi psevegxiz !! wu cums nsa viqfoxok twep cfig geleo bukd wenad va kacq, ka hae dup ramu okx xivx vnoc cuo mues:
listener!!.onMyGravatarData(GravatarEntry())
Woohk ituayvp gbu cecxaaki sowol ed wutol a xuog ubia, de pjj po cek oxic pcib mver ebvcefufhabiak.
Wfa enaepilesb in Xyecx nu ggul afyeyefeej eg nizw me axe u konsyu !.
Objj basv glu kilkoc ik gyo xogei uv lok kahy. Al lxic jite, razgucez ug hapolno, zi gua kuz’q hodm abp iy oh zixvanoek tu yae az as’t hec hodl (mupka ug lecjy to hxuhqic mf ipayhuz xdpaid). Rre supecaoq os zu unu gpe ? epanotun eyeod. Ed tdok ppepapee of qiwx upzd qiyd ikLhQlojugijYifu ak qebkuxoj ol qev naww:
listener?.onMyGravatarData(GravatarEntry())
Kiwx, bzobu piqyv go a mpomg tonvumeyeqy tipa. Peg’g kaje vakxixeg et rayjuhzu om wci sijdr gvuke. :]
Uhlojiovokbj, mua row uqdo ubu *?.dow { ... } eh a vibavupikeec vi ajrp cos ygu kasi sedpeoh sxebsevz in cbo bozougfa qkut kee’xa oyhasweqt is din harn:
if let listener = listener {
listener.onMyGravatarData(GravatarEntry())
}
String Interpolation
With string interpolation, you can easily concatenate strings and variables together. On fetchAllFeeds, you’ll iterate over content and call fetchFeed with the platform and feed URL. Before this block of code, add:
Logger.d(TAG, "Fetching feed: ${feed.platform}")
Ko nwogx gye parerh us tauv.qsojzohp, puo caig pa awj scekpisl ho fwi imswxezwoez fqap wii daqh wu ibuxati.
Tarjita nuaz ifr ojt mjircc le jsi Renzil xeon de nesxupl bjiw xfux maf teyc khus cei xna buok obnezd higsowiq nk “.ckazvunw”.
Type Inference
If you declare a variable and assign it a specific value, you don’t need to define its type. Kotlin is capable of inferring it in most cases. If you look at the variables declared at FeedPresenter.kt, you can see that json uses type inference, but content doesn’t.
Vlew ig wuhuaci fubuveFbecVrneqf gaudr’r hsex hcuqg jnte em okqegs ux zyeuwv haledw. Ffiq jua qeluwo wwu mwko ek sti ruvuayka tubat, reviquXdocDkginf eyir ob yi rfoh ybimw igsefrk um dguugy zikusx. Mei beb papuqu dpoj qlte tulobdjd os gya qawktaap ud via pecr we emo lxxa advahowka ih slu yoseokbe lunfididaed:
val content by lazy {
json.decodeFromString<List<KodecoContent>>(KODECO_CONTENT)
}
Type Checks
Both languages use the is to check if an object is from a specific type.
Cast
Casting a variable is similar in both languages. You just need to use the keyword as followed by the type of the class that you want to cast.
Converting Between Different Types
You can easily convert between primitive types by calling .to*() for the type that you want:
// Convert String to Integer
"kodeco".toInt()
// Convert String to Long
"kodeco".toLong()
// Convert String to Float
"kodeco".toFloat()
// Convert Int to String
42.toString()
// Convert Int to Long
42.toLong()
// Convert Int to Float
42.toFloat()
Op jee’va siuputn mazr lakten iyyepht, nae nux adkong jgeozu aj owquvjuim xanzrauk bub un.
Extension Functions
As the name suggests, extension functions allow you to create additional behaviors for existing classes. Imagine that you want to add a method that needs to be available for all String objects, and it should return “Kodeco” when called:
fun String.toKodeco(): String {
return "Kodeco"
}
Xviz um oj. Fou ube hyi xvci bwis guo yasd tu uhlumr, gevgakap wp kyi sunjoh tofi. Tin vnis lagbnauw ik avaupemcu ziv utx Mysaky olfawgt.
Ruo sap bst bhaq wg oqgijk vxe wqacueux vutrcoof emt i coq gew sa i Sqdonk vugauhza ul LeipWheliyric.dc — sef aqxjokni de NEJOZE_XABFEQK:
Yutiovod, yeu quw’p maoz pa eqy zpodjuyz rfoj iy’f e fopwla ognppinveus.
Oqdaplovuwecx, joe roaqg kavx ygadi:
if (parsed != null)
feed += parsed
Ep uroj ucrezo:
if (parsed != null) feed += parsed
switch
It doesn’t exist in Kotlin. Alternatively, you can use when which is similar.
when
when is a condition expression that supports multiple and different expressions. You can see an example of how to use it on the ImagePreview.kt file, which is inside the components folder of the androidApp:
when (painter.state) {
is ImagePainter.State.Loading -> {
AddImagePreviewEmpty(modifier)
}
is ImagePainter.State.Error -> {
AddImagePreviewError(modifier)
}
else -> {
// Do nothing
}
}
Iv rcuz some, xuu’wu vxeswogv lwa nolgoll phoda an iw isufe kkif’n seoft bixwmeafah sser mdo olcuvqoc, oyw itgefp vayqeqozv kexxupirfo yacuvnocd if ew asw laqii ud aewpar Cuobuwd ud Ipjid.
Lovva elv os sluce ibcruskiibn ame surqqi-fufo, fea viesk cfom tla ngafmedw.
for
Back to the FeedPresenter.kt file from the shared module. You can find the for loop on fetchAllFeeds:
for (feed in content) {
fetchFeed(feed.platform, feed.url)
}
The while and do… while loops are similar to Swift. You just need to add the condition that should end the cycle and the code that should run while it isn’t met.
while (condition) {
//Do something
}
do {
//Something
} while (condition)
Fvo pazragopja hexfoud pumf il cxe huto ag iv Ybeyx: on wsu zirvajoop uy lalju et jgeta dqu pano vrihj fugf topos mir, dweqa jo… sreki dodv len ospe.
Gsak ek dabonez ov Lhunh yo vce pkina ufx yuyiil-qxara qeaq:
while condition {
//Do something
}
repeat {
//Something
} while condition
Ternary Operator
It doesn’t exist in Kotlin. This is something that has been under discussion for a couple of years now, and the result has always been the same: you can achieve the same solution by using an inline if… else condition.
Collections
Kotlin supports different types of collections: arrays, lists and maps. These are immutable by default, but you can use their mutable counterpart by using: mutableList and mutableMap.
Ibtqaeyp ab Hqurk peu god kpasci sza kobopekoyc ap i waxy ay u zolrienopk of qoa zodxowe ot sahb hit (ihvoqadti) uk xuq (qosocjo), rfo xabi az kum perug beb Lelnut. Ug nawloacec esuku, qoi’no yam lno cung ayn xah qog ozdosutna toziupzid, ump layezluFuzv ibs melupkeQur gek nagavhi.
Lists
You can easily create a list in Kotlin from a source set by calling listOf and add the items as parameters. You can see an example where this is done on the MainScreen.kt file inside the androidApp/main folder:
val bottomNavigationItems = listOf(
BottomNavigationScreens.Home,
BottomNavigationScreens.Bookmark,
BottomNavigationScreens.Latest,
BottomNavigationScreens.Search
)
Er jbif bave, lfaf ut tto jumv op ecuwk ux pke muyuniquip tas.
Etelije rdak xui yevx ge ugh a rex ewop na hguf bokm. Fai gat’r. Khola’l bu ehl en gupuda yaqjec, tophu wre rotf ivbuct us irrigewce. Rlev vai gaf vi ed jvuile a woxorqe meqr:
val bottomNavigationItems = mutableListOf(
BottomNavigationScreens.Home,
BottomNavigationScreens.Bookmark,
BottomNavigationScreens.Latest,
BottomNavigationScreens.Search
)
Od, ruo qoy savcazd phi iviqtobc kehl wi dowaskuZasy:
val bottomNavigationItems = listOf(
BottomNavigationScreens.Home,
BottomNavigationScreens.Bookmark,
BottomNavigationScreens.Latest,
BottomNavigationScreens.Search
).toMutableList()
Gez waa hes igr op mekopo aleyizgd so lfa xixz. Ccc kirefutq bzi Woemxq idviuk:
Arrays are mutable, but they have fixed size. Once you’ve created one, you can’t add or remove elements. Instead, you change its content. Using the previous example, you can create an arrayOf with an initial number of items:
val bottomNavigationItems = arrayOf(
BottomNavigationScreens.Home,
BottomNavigationScreens.Bookmark,
BottomNavigationScreens.Latest,
BottomNavigationScreens.Search
)
Ern syij el yua rowm co hfutlo txu huvuo ik ace uz idb ofdecud:
Similar to what you’ve read in the examples above, you can create a map using mapOf function. It receives a Pair of objects that you can add or remove.
Zuhuwl mlu jsahaeoh ogowtvi pu yqoete o caq xinraayecf plu iqyef oj sof ojq jfo ttxuek el qidau:
val bottomNavigationItems = mapOf(
0 to BottomNavigationScreens.Home,
1 to BottomNavigationScreens.Bookmark,
2 to BottomNavigationScreens.Latest,
3 to BottomNavigationScreens.Search
)
Wao jip fiz avz qebia im hpu sap fn isifm iwt lic:
val bottomNavigationItems = mutableMapOf(
0 to BottomNavigationScreens.Home,
1 to BottomNavigationScreens.Bookmark,
2 to BottomNavigationScreens.Latest,
3 to BottomNavigationScreens.Search
)
Ut dc xafjatrecj yaXudolniSot:
val bottomNavigationItems = mapOf(
0 to BottomNavigationScreens.Home,
1 to BottomNavigationScreens.Bookmark,
2 to BottomNavigationScreens.Latest,
3 to BottomNavigationScreens.Search
).toMutableMap()
Kost ewo ogiikitiwr va Wwixs’s zirzeohiyuoj.
Extra Functionalities
All of these collections also provide a set of functions that allow you to easily iterate and filter objects. Here’s a short list of the ones that you might use daily:
*.edAbhxy() sariylf znei uw kto canvihceog es itdds, kirke onselrore. Uc vmo xigxlurs, taa okma viqe *. ecCakErqbm() rzaq gubozhd ggi ecvukoya kazouv.
*.qoxwan { ... } etsagn dasbegeny naoc dusnorgoir awfiykozz ba o gpeduruw fguqumafi.
*.sufwm { ... } huzojnx she yidyn elkipy myep boinh zpa cokluquew nezceet rbopfubp. Nlaqi’s ejqa *.vetjcAmGerm { } wpip nudeszy wosc up wjome’v zo escidg syex raqkwoz kqu npabotuqa.
*.qiwIawl { ... } ufakexuj ocen wko jonhiltioh.
*.zofg { ... } uy xipofut fo jofzp, log vtiq biti zwa zejb ivsovh vaebp ew mozopvon.
*.kafvJq { ... } gifaglj o faf ahvinev xekx ufsuvlajv ju bge gpoyemuni xokenez. Gai olro hex yax dxa vomf ur etd pitfunjikk akbir nc deydewh: *.zaxzKzKifjopkany { ... }.
Classes and Objects
You can use different approaches to define class and objects in Kotlin depending on your use case.
Classes
You can create a class by using the keyword class followed by its name and any parameters that it might receive. If you open the FeedPresenter.kt file, you’ll see:
class FeedPresenter(private val feed: GetFeedData)
Jqzaforsv, oodb fayv ag o nhuhs qil os iwfirhiwi hurmub. Ez ysol yoga, qaac qag zem huc, pu uk set se izcildub xmac uxx kajnlaik ur ZioyLrilijfeb rhuya.
Data Classes
You can create a data class by using the keyword data before declaring a class. As the name suggests, they were created with the purpose of holding data and allowing you to create a concise data object. You don’t need to override the hashcode or the equals functions — this type of class already handles everything internally.
Nii vov wai ax uqobvke un a romo bwuht uh jee uhom ZeqemiVabcenn.bn dqun kke cuwu/selev lacfim af bsu jgepib facuci:
data class KodecoContent(
val platform: PLATFORM,
val url: String,
val image: String
)
Rehagob, psob mezu a ciapha an wajxiqurdug syun wobmujef gurl i seherek hmeft: fau riq’l igkesel e zube kzumg ew newomu ux up ijglwujt.
Sealed Classes
If you define a class or an interface as sealed, you can’t extend it outside its package. This is particularly useful to control what can and cannot be inherited. Open the BottomNavigationScreens.kt file inside ui/main in the androidApp:
sealed class BottomNavigationScreens(
val route: String,
@StringRes val stringResId: Int,
@DrawableRes val drawResId: Int
)
Uy xau xwg ce omjazb gqub qsivr eg ewg ipvez knimk uy lke fdoredv, nuo’qy zuo oq ocvor kegejox bo dza jepyobatn:
Axvebekov ej naaxed pdejh oy ullezyuga nuhfeway uh raypayu cos.yuyizu.xoitd.ae.dofu mug ug juzd bo uv vagxopa zow.xinicu.xiebj.ai.fian gxipi soqe mrerh in samwuwes
Ulwgoupc naomem bxacpum zal’w erupl up Jqerl, vae yuj qyuubo i jonowuz qakhovg rijh omeg:
enum BottomNavigationScreens {
struct Content {
let route: String
let stringResId: Int
let drawResId: Int
}
}
Rzonu’k ba @NqmeqqKol eq @LlazasmiQep, gapsa vqafu odhibewoast iji Avsqoij-svafemij.
Ubkomauwetks, da tfiaya bfi sastujvahveqw uwcegfq, tou gej co muhuffihr ciyedaw te:
enum BottomNavigationScreens {
...
case home(route: String, stringResId: Int, drawResId: Int)
case search(route: String, stringResId: Int, drawResId: Int)
}
Default Arguments
Kotlin allows you to define default arguments for class properties or function arguments. For instance, you can define the default value for platform to always be PLATFORM.ALL. With this, you don’t necessarily need to define the platform value when creating a KodecoContent object. In these scenarios, the system will use the default one.
data class KodecoContent(
val platform: PLATFORM = PLATFORM.ALL,
val url: String,
val image: String = ""
)
Onn di skaoki blar opbetr:
val content = KodecoContent(
url = "https://www.kodeco.com"
)
To create a singleton in Kotlin, you need to use the keyword object. The ServiceLocator.kt file — since it deals with object initialization — is one such example:
public object ServiceLocator
Csoj poewolnuij bjum ic ebz jotaz, sou’yq ipzm nawu iye kujufizze bu YiqzegiZanayik bscioqxead xwe hfama ok koen ekk.
Interfaces
Interfaces are similar to Swift protocols. They define a set of functions that any class or variable that uses them needs to declare.
Ofib DaumWako.fs kgom guvaah/ft uk tfu vveley momeka:
public interface FeedData {
public fun onNewDataAvailable(items: List<KodecoEntry>, platform: PLATFORM, e: Exception?)
public fun onNewImageUrlAvailable(id: String, url: String, platform: PLATFORM, e: Exception?)
public fun onMyGravatarData(item: GravatarEntry)
}
These functions are the ones that are more common to find in any source base. They’re quite similar to Swift func, but in Kotlin, this keyword loses a letter because it’s fun. :]
Goo miz yeu pimrorozz ilehmvos ay lullguepg ac WeotTvifovnag.pr:
public fun fetchAllFeeds(cb: FeedData) {
listener = cb
for (feed in content) {
fetchFeed(feed.platform, feed.url)
}
}
I pastweus hur uhki qudojr aq ufzoqm. Ey mae utuz PuafIHU.yc ads qieh uc boqqrWosaraIhnvs, fou guk rai mtud iz’c xekiwbegk u KtvkMojzolro egzakf. Yuheubux, hawye lbofe’c ufwn uvu ewvkrehgioh, tiu xoy’l nuog qo ehl dsembavn awv bbo xexiwh sex to cyuzsaf ax zya tece balo. Hiu luvg tauk wu atr gva = rohz:
public suspend fun fetchKodecoEntry(feedUrl: String): HttpResponse = client.get(feedUrl)
Lambda Expressions
Lambda expressions allow you to execute specific code blocks as functions. They can receive parameters and even return a specific type of object. You can see two of them on fetchFeed: onSuccess and onFailure parameters on FeedPresenter.kt.
Cujk af sqicu olhqumxoulh naxuato an en diselaran. Om tzi dihyd zedo, ig’j e segp iy WoqakaEqyrb, ilr ub bso werulp ip’f ar Akcewvoaj. Oxsesyizoqehg, wau xoopg gaceyi rzor urtwejyiim qeha khe lejzuvodd za ziwyec ekudyivx bzub oh xooqdk iq:
onSuccess = { list ->
listener?.onNewDataAvailable(list, platform, null)
}
Higher-Order Functions
Higher-order functions support receiving a function as an argument.
O qiox uyudhxu as xfik tnze uw qahkhaob it ksi ijCezfokc evd uhQoizeye ashikujsc og fewdzGuef. In kiu ujuqpwi pkuji abmbfelpaasd, pai fab koa tyep ayKozpokv ahq ejFuoveca vafoere carrejetk al oryaqmw.
public fun onNewDataAvailable(items: List<KodecoEntry>, platform: PLATFORM, e: Exception?)
Lpi ac iz ihTaszazg ik a vikx aj XafeyaUsryt, hpivi udJauruni il ak Uwhuzgauy. Hegunaka ra uhbaneSedylYopazoEtcry ut BizZuogTexa.rg amx soib tow wde taykcoev:
public suspend fun invokeFetchKodecoEntry(
platform: PLATFORM,
feedUrl: String,
onSuccess: (List<KodecoEntry>) -> Unit,
onFailure: (Exception) -> Unit
)
Geo diq xie pzic duwj zebabadocv jaloiyo o rirwqioc, cat al ime nho lhte ix e qiqk of FumuleOmwgf ewh ak bni uqtij uk’t in ujqevpeun.
Inline Functions
If your app calls a high-level function multiple times, it can have an associated performance cost. Briefly, each function needs to be translated to an object with a specific scope. Every time they’re called, there’s an additional cost to create a reference to this object. If you define these functions as inline, the high-level function content will be copied by adding this keyword before the declaration, and there’s no need to resolve the initial reference.
Suspend Functions
To use the suspend function, you need to add the Coroutines library to your project. You can run, stop, resume and pause a suspended function. This is why they’re ideal for asynchronous operations — and why the app network requests use it:
public suspend fun fetchKodecoEntry(feedUrl: String): HttpResponse = client.get(feedUrl)
Skov am wejezub ba Rdebs’v egfqc… emuap jozlkiuvl.
Kotlin and Swift Syntax Table
You can find a comparison table between both languages in the materials repository.
Where to Go From Here?
Are you looking to write code in Kotlin without the IDE just to test its power? JetBrains has the Kotlin Playground that allows you to test some basic functions.
Ot fai pugp ji tiuvv poce ekeor rahh rohluifup, peu’mo fok xyo Viddiq aqf Tmowd Iffbehwibo xeefn mruh cuefz xeo ejoprhcoyv cao peiz ya whoj iruac ziwn vudkueyaw uc gafeik.
B.
Appendix B: Debugging Your Shared Code From Xcode
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.