Android Development iOS

Kotlin Multiplatform

July 14, 2022
Kotlin Multiplatform

A few weeks ago I was try­ing my best to inves­ti­gate the plau­si­bil­i­ty of what Kotlin Mul­ti­plat­form Mobile could be. We’ve heard the promis­es of write once every­where” before but they have always been lim­it­ed in flex­i­bil­i­ty and in my opin­ion, nev­er actu­al­ly felt” native in the end. We’ve had expe­ri­ence work­ing with Xam­arin, React Native, and Flut­ter and I’m sure any­one involved with those projects would be a strong advo­cate for con­tin­u­ing to work in any of those frame­works going for­ward. Per­haps that comes down to the spe­cif­ic imple­men­ta­tions, but to get fea­tures unique to plat­forms you end up writ­ing a bunch of plat­form spe­cif­ic code any­way. At the end of the day you are find­ing your­self say­ing… if only I had done this native, this would be so much easier.”

Yet, the more I’ve heard about KMM the more I’ve been excit­ed about the pos­si­bil­i­ty. Large­ly because of what it is not try­ing to do. It’s not try­ing to recre­ate how the view sys­tem works on either plat­form, it’s not try­ing to turn your web­site in a sin­gle web-view, it’s focus­ing itself on the busi­ness log­ic for your app and because of this, I think this has the poten­tial to become a very a pow­er­ful tool.

So, I start­ed play­ing around with a very sim­ple idea. Basi­cal­ly the sim­plest app I could think of. What if I could pull down my cur­rent weath­er fore­cast from the inter­net. Seemed easy enough, but I quick­ly learned that some of the depen­den­cies I’m used to were not going to work in the KMM. No mat­ter. There are already a decent num­ber of libraries avail­able writ­ten specif­i­cal­ly to be com­pat­i­ble with KMM. So I was on my way, and pulling down data and dis­play­ing it came togeth­er pret­ty quick­ly. But where we quick­ly launched into prob­lems was with ViewModels.

Gray Areas #

What can be con­sid­ered busi­ness log­ic” and what is con­sid­ered state” or view state” can be pret­ty sub­jec­tive. After read­ing a bunch of dif­fer­ent blogs, I thought it would be neat to have an event based sys­tem that each plat­form would be able to observe and change the state appro­pri­ate­ly. This quick­ly became annoy­ing hav­ing to use spe­cial libraries to con­vert things like LiveData and ViewModel into a plat­form agnos­tic ver­sions of them­selves, and although it was do-able con­stant­ly felt like I was shoot­ing myself in the foot. The more I thought about how to han­dle this by mov­ing log­ic far­ther up, the less it felt like it made sense to have in my shared code. I ulti­mate­ly start­ed think­ing that the best thing to have shared would be my data lay­er. Pack­ag­ing up all of my API com­mu­ni­ca­tion and mod­els into a sin­gle pack­age they could both use is appeal­ing, but I then learned the down­side of coroutines in iOS.

Asyn­chro­nous Annoy­ance #

Up until this point, I felt like every­thing could be rel­a­tive­ly han­dleable by due dili­gence of a team, work­ing togeth­er and defin­ing lines on what to share and what not to share. But work­ing with suspend fun in iOS proved to be the fea­ture that made me start to ques­tion how help­ful any of this actu­al­ly was.

One of the basic things I wrote ini­tial­ly was a func­tion to pull down the weather.

suspend fun getWeatherForecast(): Forecast {
    return api.getWeatherForecast()
} 

Pret­ty sim­ple. Call­ing this in Android was as sim­ple as cre­at­ing a scope to launch it in.

viewModelScope.launch {
    repository.getWeatherForecast()
}

How­ev­er, when it is cross­ing over into Swift you lose all of the under­stand­ing of what a corou­tine is. You are left with some­thing like

repository.getWeatherForecast { data, error in
    if let forecast = data {
        // do something with the forecast
    }
    if let actualError = error {
        // do something with the error
    }
}

Although, I don’t love writ­ing that every-time, writ­ing a thin wrap­per around all of the API func­tions to make it look nicer or to con­vert into async/await wouldn’t be the end of the world. But, as far as I can tell, you had no real way of inform­ing the corou­tine to stop run­ning. This may not be a game chang­er, but does seem like it could result in some inter­est­ing issues down the line. 

Ulti­mate­ly, I’m not ful­ly out on KMM, though I will say that the use case where it would be suc­cess­ful is prob­a­bly lim­it­ed, at least as a first attempt. Hope­ful­ly with time, we can look back at it again and see what improve­ments have been made. A future where I am only writ­ing busi­ness log­ic tests once is a good one.

Click here if you’d like to look at my sam­ple project.

Scott Schmitz
Scott Schmitz
Staff Engineer

Looking for more like this?

Sign up for our monthly newsletter to receive helpful articles, case studies, and stories from our team.

Information Experience can make or break a product
Design Process

Information Experience can make or break a product

January 4, 2023

Kai discusses how writing impacts user experience, providing an overview of the types of writing that are involved in product development and how to approach it from a very high level.

Read more
Between the brackets: MichiganLabs’ approach to software development
Development Team

Between the brackets: MichiganLabs’ approach to software development

February 12, 2024

Read more
Chicago Roboto 2022 Retrospective
Android Development

Chicago Roboto 2022 Retrospective

August 11, 2022

Scott Schmitz shares some notes of interest from talks at Chicago Roboto 2022, an Android community conference, that took place August 1-2.

Read more
View more articles