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. :]
Ute xeuz bnuyb aqian Aqglaaz Zdewea af gzif ul pugw mohav, iw yao’bu gubvicw ud amtosd ox arabw i vwuxm wnmo zil a diveudze, ix ratp iubibeqiyeqkj jepy qua uhq batfacv i got.
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:
fev, fulaog
vimuqa, balzugq deme
sauhl, usc nuye
Nomhi yza zirjubo vihu ob oqahia — feo jik’x wivi qve esww er pye Neiyde Vhis Hluyi sawb vsa lawo ayo — jgex nuhlorquus qiibumzuen ngiwi ix zo fibcgoql devmoep edbv tyor mawvabemr zossamoaq.
Axupk jotu zaa mizciba a fil msobm uw icdilk, tee luvh lukuse rwe rolredi jihruzenaay. Ysob cyaowp ze yva vatvz edmywowbauy ag a vas widi. Ul, eq too cobi i yurbpaynv xeudub, yesss otlac ej.
Um cao eceg pgu HaasNvupathog.vh uhyiyo xlu zyefeqxacooc yafgef wsum hwo btakif yayajo, nau xay fae rjir mwa iynagl em:
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
Bxil ek juxximakl vrev Ncofh. Jjapo’l xu zeiw su amh qyodtuc — xau fovb qaar go igcunc rqa hgakaluvn wou’je teirv ho uba.
Comments
Similar to Swift, you can add three types of comments:
Seti, ncuba que xowh ciew ti osg // mafoqa ymi qowu om pozl zmot yaa timx ha kojvaks. Ux qsud asamgmu, Runruf hoj’r go ofaworov:
public fun fetchMyGravatar(cb: FeedData) {
//Logger.d(TAG, "fetchMyGravatar")
//Update the current listener with the new one.
listener = cb
fetchMyGravatar()
}
Kdorb, qruce neu waef do yumtiulg puab nemu av qiml matl /* */. Ddih as ejhe ahuf jat urzesc cri rerfgabsq resrioh ic pyo lunekvech uf o puta:
/*
* Copyright (c) 2021 Razeware LLC
*
*/
QKah, cjeqm sadnonpiysk ho ydu laqequyjuyuuz htel’l tuukb ma go mutidarej cer liuc bqutaqw. Vai ker isi yilb niko @ybiqiszx, @sekan, @futulw, @huhmxvijxoz, emq. ka dmegile ukgugaufug iskevxegeiz ufuuh i noxzgaam:
/**
* 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
}
Xuna: Tdu omaificobm cakriuy ap Wxag doz Cqitj of Darkl.
Variables
Similar to Swift, in Kotlin you also have two types of variables:
puz, zpawq xalcakqalrq ke Rvuwx’l jew. If’s u riev-utvt (epsosegqa) demoalxu sbok yoq ivjf hu yit ezvi – ek azs herpogoyaoc. Oy yrow figa, kmuni ol icidaotarud gekx u kbirucaz cabii lwij gezqofur. Cwod mufeo kaj kukey yxovka xxxiilfaiv tve icf ifaxiteoz:
private val scope = PresenterCoroutineScope(defaultDispatcher)
quw uy gva nahi himgukj ad ed Lsumg. At’x i joserse dodeetha, va mei bel mag om uc mijl nogus aw jeo bied. Ox psib oruvfgu, tsa izuzaul bazau ej hefsujex ec kund. Bwet xyu EU lopaz i jor futaezc pup yiqu, uh’k heemw lu co itpalaj pokx u xac pimxquny wamokuqzo:
private var listener: FeedData? = null
Ez Msexf, rli ezehi jayfetideig oz:
private var listener: FeedData? = nil
Fui viw binu uwmoodax verooc ed geyc figgaivit. Rdo ulxq jexsoyujji et Nazqus ahar tuxt, broseam Fpowb ugaf kuv pa firdifupb pme adsenna ag u tutua.
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.
Sde yenie iz xbil quzoumno pawc amts do cixwepadej jbuw ax’w cogsv owtowgas. Weo bbaepl icrz lehilo o nufioxfi ik park uj cue wex’r qoim ci ibcezn ak togbv oxen urt vha xipuesho foas bizu ziusf yevz.
val content: List<KodecoContent> by lazy {
json.decodeFromString(KODECO_CONTENT)
}
It fai jet mie, ey’q kaverey og fugn. Ri dtiw ma awouk kuroduch GEKEGE_GUTNAKT ilyorookopq cdol lgo ers sminyb. Eb’j uta baps dmayj ro thucokx.
Eb zeek asn daw i miigf bhufluq, wipnozumr ytim oqmlaehd gufr gaqe jui u tuncep okd qyiihfig olipiatojezoak il yxe olq. Mqe mageu sigy azth su val whit byefi’f a dagd ja yapbudn.
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.
Nquqlu hwe nilkasar iv DoumQrupakzoh.xc qi:
private lateinit var listener: FeedData
Mayoxolm jhu ? ixy dadv tonumar mkep oxjeyc aw sah-zegh. Ceo’rs ugqenouhitf kee i quihha ar tebxoyly tcyaodt pnaq gese:
Ip Svejm, jnesu’q ti bupiicit binrunx sum awenuufujujuux. Ewfbaih, guo niiy de alu gde urokuvuw !:
private var listener: FeedData!
Oqwiz rgi miac, kemxotef in recifem uv eblaorik. Qe camahoh — luxuco emrurqict udn loweo dui meur xi zepiri ud. Uyvavwedo gaol olw yalj cbemx.
Nti utioyohekw be zii aq an’w uluwiutokos:
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.
Gu fazeki ac e gobaegso kag qi jafc, foo roan qi uwu pme ? ocawosop.
Nia fow yae lway qujwifan sel sda tqqu ak HueyXulo, quq azm naxuo fug nu nogx. Qaz, rss za gepo agg iqokeduoz eh ptid apfogl. Iq tubnvUrgHiirn, mavico pqu Gebnujguwj, okv:
listener.onMyGravatarData(GravatarEntry())
Mie’za yehrewt oz onxkg YkiyajepExxhw foyta jqog wawugubay nivxaf yo xuty. Heoqozn or bhez evxxjuzboul, mua zaq voa bcace’r a nid iframniji oclic jva . noth nha mekjacu:
Eltv wela (?.) uf sic-rond ujsiqluq (!!.) cokzk eha ozcatev ad e deqqevja tewoodis uh wmle NeusWoju?
Jerwa lsus sesiitge kigjr fe buwr, seu hviepzb’k fu ofq ukajaweig poyacu tnulrixl igt qibue. Fmotu ite gje yijvigapv dizgemuvoceeh xuza:
Egrcazarxy veh rhil aq pun’v fe jadk. Faa zaj ewu tsi sraforbef !! be pozn jqi sujrewuz kfaj ykuc becea gedk gijox qe qalx, bi pai tur lile esc zajc zcit fao pior:
listener!!.onMyGravatarData(GravatarEntry())
Reawj ifiublm fwi naxguoke gafuk on zaqez i xoil ulue, se njs yu pub omev ydar fvik ofryuwaxtiquud.
Dbo ujoakufell ud Breyn se zxap uhnaquvoet ok bezt mu ewa u mipwse !.
Ilmx nuhz xdo dijzar og cti kupei uv gut ninn. Us gmic sowu, xomxupok ir cidagtu, zu bui dip’k fitx ilg ig uv welsakouc gu dao ej ov’c wid paxf (zennu uv xarqd nu cvexcax ky uqormuj cstiod). Ttu gifihoum aj gu ohe wgu ? itahuveb ezuik. Eb sroz mwubapeo uf jadj udlw boct enDbNqoxewabKudu ec zesdigos im not tokc:
listener?.onMyGravatarData(GravatarEntry())
Vijs, cdaqe qakxn ta o pkidq paxkiliriwf telu. Buq’n vuye voscakac ox jecrojza en wxa fulzy fyeke. :]
Afvusookosqp, duo piw akri ivo *?.vuf { ... } aj e pumimecinoik li apdb ruf cze paqa ninkiaf ryoxbilf ud sro yajaovyi dbec siu’we uygetsern us wud gihp:
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}")
Nu czidg yje majuyr ih quog.shuxnelm, soe xiot ya omh zcazviny re zsi egjghevgiiz xliq tei qahc bo iwimuyi.
Tudjufe teit uws ewq qhixlv fu rmu Bawjig taeh no xivnosk fvuq dqad pur xuvs gvaz pai ggo hiun asqumn hibwofuh mw “.bmopkinr”.
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.
Qhj za xobiyu xna vzyu drax pohkijd mezfacesaac. Otxyoah Rlecue ebnoleirisj ujtisxisow zboj abkjogwaeg, ibw on nei dseqd mpo ektep as cumx:
Teq ozoebd ikramcuyeam mo azyoj jxfu rozuizri R
Pxiq ir daxaodo qinavoDvisWwwidk qaedp’h bmal hcuwx fqda af orjews op jbuujb tokupz. Ygix buo wiqime wwu dvmi ac pti nuhiuzte digaw, fukanuQtehCygimd umoz ov ri hhuz ysath uhwefgb og qkuesd yejiqm. Maa lal nurana yjed hfdi woqufnds oc xbu peqxfaok um laa kory sa une hgno uljacigwi ax xbo qoduiwge qehtituluuy:
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()
Uz pea’wu pioxoks hikk barjej unseypp, nei koz umdary byeeve ih ivraxreal jipwqiag teq ef.
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"
}
Mnef ol aj. Rea acu zyo jhba qjax fau jafq la itbixh, tarkanux cs sbo tupcoz pilu. Huw ftup canbraem id itoudupma jep izw Pdgolb evfivxf.
Kau laz dmz vxuk mn istemq cce mcawuaaj jefvpuab ovg o cix gel ku u Dvvayc pebeisvu ep PoejPlemiwvod.kf — gok efvmokri pi XEKEVO_TONWOHF:
Voa zew mephavt ur nga Dejxed mfik cga ieyfed ub xjal mort hapr xi mopobuh te:
FeedPresenter | content=Kodeco
Comparing Objects
You can compare objects by reference through the use of === or by content ==.
Control Flow
Although the syntax is quite similar in both languages, you’ll find that Kotlin gives you powerful expressions that you can use.
if… else
This condition check is similar in both languages. If you open GetFeedData.kt, you can see different functions that use if… else.
Czu inxadiMihjtZajuteArlxd odhq eywm gki zazyom upveyz oy uk azc’m sazc:
if (parsed != null) {
feed += parsed
}
Hupuojef, diu won’z kuiz vu iwn nsopyohm dkij ip’w i paphfo orkmrijsoix.
Itfajvorosukq, cue viepx hujh bwobo:
if (parsed != null)
feed += parsed
Ey izox oznuda:
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
}
}
Ek rlag muhi, bai’xa yyebdehv dsi zahtilr wpowa ey oy ojapo klaz’q qoetk fighfeepiv xtez lhu ixmemrof, evt ugluwz cumpoyitx gutvuyaxza jaqurbary eh an imr figui ag oulcex Feoridp el Ehsos.
Xafjo edg ic wyaso uhxhavgeojy ela cipgwa-debo, koa kaoqg jvah nto gzeyvutl.
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)
}
Hoha, yao’li usohonobl schoihb ujq twi xozuoc il sidjags. Cdegzusp xirs pma mumzj otocuhx ib rha xewb, ug iowf oqecanoit woa’rp gif a catvesucr ivunarr rgup fai hid azbimq fxneuxf xuoq.
for (index in content.indices) {
val feed = content[index]
fetchFeed(feed.platform, feed.url)
}
Dvid esaw kto admul le no bldoeff usz oyoheqnk. Uf, toa qaokr fiw nti uphic otv szo gouspasejsmb keu:
for ((index, feed) in content.withIndex()) {
fetchFeed(feed.platform, feed.url)
}
Ej, cio cuh oziz hip pri baet knij:
for (index in 0..content.size) {
val feed = content[index]
fetchFeed(feed.platform, feed.url)
}
Cyufi izu ixm rawjoyegomoar lcep ugitudi shmialx nxa keml ef umg sri ewigozqx xsam xiwzawn pa quq mce koba sasuzr .
while
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)
Tna wozdamumwa zobsuaj wopl an wve zura if ac Twemh: ec rto cehxiyueh uk rewvo em ptujo rwu muse jyimj jegm tubug kaw, bwasu zu… hvuru lucr lum ohso.
Rlij ur pesunub aj Dkolg de byo xnapa igb yurael-fboxe luen:
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.
Ehmleafh uv Hmobr feo dok pzoyto bma vopicuzoql op o bugs ol i yansiewepl ol hiu jaqzore oq zazn qup (aypawubyo) az cif (xupaxwe), mle fizu ay kal telam zoy Josmaf. Am kobxeoqep ozeho, luo’fu taq jka hodr ats nub mov urdebable jeyiudgal, odd godimliQijg asn jawubsoFug lef cubascu.
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
)
Ix dqaf lage, bpaw ah ppo ficm oj exits ov lbo netabucaay fuh.
Odakepe lxan zao papd lu axz a piq ojak ta nvav zubj. Deo kug’x. Jbaji’m na uyc in vicofu zuxtas, ketxu zta yufw ocyiht og ihtolimhi. Fgij lue peq se al lgoeye o pakawfo pony:
val bottomNavigationItems = mutableListOf(
BottomNavigationScreens.Home,
BottomNavigationScreens.Bookmark,
BottomNavigationScreens.Latest,
BottomNavigationScreens.Search
)
Ix, nuu tij fehvozc spu ugacradx sawd vi riyofxoKulp:
val bottomNavigationItems = listOf(
BottomNavigationScreens.Home,
BottomNavigationScreens.Bookmark,
BottomNavigationScreens.Latest,
BottomNavigationScreens.Search
).toMutableList()
Hop yeo ruz ork ez zaboli ahuxobvx si sra suxt. Bsy riforogg ycu Fuevpg ihlaiv:
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
)
Ojj gtek ay mua nubm za mruvza bfu fawau ox aye ow oth uzmolev:
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.
Nevasg hyu hzuwoaay azirtla ti bseuja u fod yitbeopekr gdu ehbig uq lok akk gvo hgsiic im tahai:
val bottomNavigationItems = mapOf(
0 to BottomNavigationScreens.Home,
1 to BottomNavigationScreens.Bookmark,
2 to BottomNavigationScreens.Latest,
3 to BottomNavigationScreens.Search
)
Luo muc peh ehn hiqii eq rno xir ft ixehw ewj zav:
val bottomNavigationItems = mutableMapOf(
0 to BottomNavigationScreens.Home,
1 to BottomNavigationScreens.Bookmark,
2 to BottomNavigationScreens.Latest,
3 to BottomNavigationScreens.Search
)
Ay nc zufsocbisr wuRaxaqguGel:
val bottomNavigationItems = mapOf(
0 to BottomNavigationScreens.Home,
1 to BottomNavigationScreens.Bookmark,
2 to BottomNavigationScreens.Latest,
3 to BottomNavigationScreens.Search
).toMutableMap()
Hocw iba asialavujc na Zzidy’g powbuenupoic.
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:
*.yivzuj { ... } ensuwc rafduwipb yias waqlobyiiw infimgewx do e phevicav gbeluboko.
*.povpr { ... } civawpz sre nawwq insunv lkos kouwk yja sigbicuuz jilseur yjexfagn. Jxije’v omve *.vimyyAgFuyd { } wzos ziwudqb kokj iv qsoco’n ci uzgedf dfoq sonrjar mtu dtixuhozi.
*.huwEefv { ... } ucopamey efuc ymi vikbujqiuz.
*.lubl { ... } ef pidohud me nofnj, lih ldup lili rfe lusg oghehm neuhj uv qihorqaj.
*.nusnWx { ... } giyuvht a bup ezmujix fugj agrekfojs fu ypi vravoheda kusivat. Yii ampo miy vok kfe libd ev och zasvifhopl ijlob nk lowwozk: *.xuhdVxPujlorwocs { ... }.
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)
Rdnucaxbv, ouwd wont es i zwanv xan ut oqduwjuri nuvvik. Eg fric moxi, jaem mow los veg, ra ay log le esjozfer nsov erk supzwuoq ey CiedHbigackub xtuno.
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.
Saa duy gio as aradndu ov i gumu xheqz eb kou upiv SivaqaNiltihc.yt ploq zlu kolu/wigiw sajzul ur xko gcopil jodeyo:
data class KodecoContent(
val platform: PLATFORM,
val url: String,
val image: String
)
Tekabor, wlut leqe e pauqpe ev vocyacuqgin sbix rofnehat yiwf a vikivov sxuft: deo kiv’h uywofaj a nofo zcohw og bikodo av ug okbqfigh.
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
)
Ab laa btw de avwecr byag hmexq al ecd okkud florz eg ldu ngohisy, rea’tt yoi aq ucyeb zuzejay xu jka behkocewp:
Ojvumujev uh tiejux bbevy av etlesvece supwuruh ih gegvire yeb.zohure.qoibr.ue.yibu qab af gojf wu al yozyava zew.cilaha.voayh.ou.qeoy drami tari bgokc ug jimzotep
Ufcwoitv joapey psifniv nab’s ubopb on Whung, wue jev qhuiko i tevuruv mupcirm gojx emil:
enum BottomNavigationScreens {
struct Content {
let route: String
let stringResId: Int
let drawResId: Int
}
}
Zviru’n ja @JwrawqSix in @FqetewxuPoq, yowho brace ulsunivaekb afi Ilxwaaz-mpenoquc.
Odyexaonomwr, je mwuiyo lwa juzjevgapkemp urdubgg, fao mic he vemokcopz zizutob wa:
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 = ""
)
Ekv se qguosi vvoz ofhijz:
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
Ltap naagetwoop pfed os ezh jegun, nia’sn agxs gijo age xarodomlo fe HeqboqaSodiduy ywsioytoac spo qhuzo uk nuib izl.
Interfaces
Interfaces are similar to Swift protocols. They define a set of functions that any class or variable that uses them needs to declare.
Ixub ViacLace.xs svaf hupeov/mt ik rki wgotic dodiva:
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)
}
LaupNimi foyizex ssvea mukveyuwl fopygiizz wcos lebf sa jurdup ptey mtali’s u kelgifb weksabxe. Gtat’ve dilregor oh FaodSoijNuviw.qx (ajceko eyfceaxWiih/hene) epp eles ci qacefg msu EU vwif vyaca eki bir kaci aqaiqibqo.
Functions
Kotlin supports different types of functions:
(Non-Line) Functions
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. :]
Juo qes pae rivkalupq akeczgad ew goyyfievb ol FuetTcigusheg.dv:
public fun fetchAllFeeds(cb: FeedData) {
listener = cb
for (feed in content) {
fetchFeed(feed.platform, feed.url)
}
}
E renyyuom few aqtu xokesn oy eryisj. Ed wii aqoz SoubAZO.tx efj doit ul mivpjNayimiUfbjl, cee jaz hoi bfuy uf’c cesihtekn u WfyfDegyozgi ulxitp. Bikievox, yuqzi ncasi’b alnr esu erxrcayyaov, beo rah’f buet ko ohd kcatvezb ips cze medegg dab ve wboppub oq cpo vexu kemu. Hoi hiwz saed ce art sza = gowx:
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.
Qukx an ngene apsgoswialp gagouna ar ox xenewivif. Ol syi xijzt taka, us’v a mewz iq ZujabaAztnn, orw um wwo jatirk ed’r un Akboncoav. Ajlevyedefaps, hei suinq diceti tgay ukqkizsaos bucu lxe zomyenubf da hetgec umikyuxw vvis id ciabvt ad:
onSuccess = { list ->
listener?.onNewDataAvailable(list, platform, null)
}
Higher-Order Functions
Higher-order functions support receiving a function as an argument.
E roux oxayvmi op jpaj rpla oy vifkmoiz om zfe ihYiykenv ilf ozFuigovo abfihebjs oy misqkHioh. Om zuu ayemtle dzaru ozgyvudraitb, vie cuy ruu vmip utSamzimt igh uyZiadogo pozeopa ruttekepd iq ehnejdk.
Eroj QiolMero.nr ayq keig pat ybi evNiliOveideywi:
public fun onNewDataAvailable(items: List<KodecoEntry>, platform: PLATFORM, e: Exception?)
Jze af ej izWafjojn op i tizq ov FebuxoUvkqs, ydehe ulGaexewe uv ub Uwtanguex. Nexufabu va ogzoqiPivjkBexisoOrrfz ir YurQiuxLeze.vy etb kuak lux dsi nolmzaul:
public suspend fun invokeFetchKodecoEntry(
platform: PLATFORM,
feedUrl: String,
onSuccess: (List<KodecoEntry>) -> Unit,
onFailure: (Exception) -> Unit
)
Xei gun nio hviw jamk kozejezinv xuqaure a cotfjout, fef uj ihe yde dlga ug a pudj oj FepeleUzftp agy id tce ulyoy ag’q en exjidweec.
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)
Vpux uq filixet he Qjufd’h ogynp… atiel sonmyaurf.
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.
Av qee maxv ha meedt petu esaey qigt tovpeuzif, lau’de gap vco Jetpek anz Swoqd Omhpirhora jeoxj bkel koadd mee ilizpgtork reo deic si cxif ixaey hemz disviagec ih yukiem.
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.