Increasing Stability in the Kotlin Multiplatform World

A few months ago we published the Kotlin Multiplatform mobile app for Droidcon NYC, then updated for Droidcon SF.

The version built for NYC was largely coded while there was a lot of churn in the multiplatform world, and before the KotlinConf app was available. A lot of the libraries were either hand deployed forks, or didn’t exist.

We are entering a phase of ever increasing stability in the Multiplatform world, especially as it pertains to native and mobile development. In the last few talks I’ve given I’ve been promising to update the Droidcon app so it would be the most up-to-date and feature-rich example of Kotlin Multiplatform for native mobile development. While still a work in progress, much of the app has been updated.

Current Status

We’re entering the phase of stability for KMP. There are still plenty of things that need improvement. With regards to simply publishing libraries, the Gradle version split is really the biggest issue today, although that should be resolved in the near future. Publishing Android libraries (*.aar files, not jars) with the new multiplatform plugin is also an issue, but that’s a little out of scope here.

Gradle Version

The Kotlin Multiplatform world is in sort of a temporary crisis with regards to gradle versions. For native mobile development at least. All of the Jetbrains’ libraries are on gradle 4.7. New versions of Android, including the version of Android Studio with multiplatform tools built in, require gradle 4.10. This would normally not be a big deal, but without getting into the weeds on why that’s a problem🌿, just understand they’re incompatible.

Use Intellij, not Android Studio

For today, until the Gradle issue is resolved, you can’t use Android studio 3.3+. Download Intellij

Library Updates

Many of the architectural libraries we’re used to in the native mobile world have analogs emerging in the Kotlin Multiplatform space. We’ll be updating a list of resources over time as new things emerge. The Droidcon app started with a lot of hand rolled multiplatform code, but that is being replaced over time as more formal libraries mature. Below is a list of what’s currently in the app and what’s been updated.

SQLDelight

SQLDelight with KMP is approaching full v1. At Touchlab we’ve been working on the iOS implementation side of that equation. Droidcon now has what will (probably?) become RC5 of the SQLDelight library.

SQLDelight is still primarily an Android world library, so it is being deployed on gradle 4.10. Because the KMP world is still largely 4.7, we forked current SQLDelight and have published a version that works on 4.7. Otherwise, this is what will ultimately be SQLDelight 1.0.

SQLiter

Our first major KMP library publication was KNArch.db. That’s a port of AOSP’s SQLiteDatabase stack for iOS/Native. That “works”, but on reflection, was not really the best approach (part of Droidcon SF talk about that). Our new library, SQLiter, is another sqlite library for KMP. However, the goal is a minimal layer between the client code and the underlying sqlite3 library.

The latest SQLiter is providing the iOS driver for SQLDelight. That’s its own pending blog post, but it’s in there to see in action. There’s also SQLager🍺…

Kotlinx.Coroutines

Coroutines are a big deal, of course, but they’re still single threaded for native. In the short term (which is until they release multithreaded coroutines), we’ve added a background task processor that allows you to call it in a coroutines context.

val session = backgroundSuspend {
sessionQueries.sessionById(sessionId).executeAsOne()
}

In the example above, we’re getting something from the database, but running it from the main thread. The lambda arg to ‘backgroundSuspend’ is run on another thread, but the value is returned to the calling context in the main thread. Coroutines FTW 🙌.

Coroutines also show up in the Ktor calls.

Ktor

Ktor is the networking library from Jetbrains. It is both client and server, and coroutines enabled. While doing the original build out of Droidcon this was in a significantly earlier state, but it was time to upgrade.

Note: Ktor works, but DO NOT upgrade kotlin to 1.3.11. Until the next point release of Ktor, stay on 1.3.10

Kotlinx.Serialization

A few months ago only the raw json parser was supported in native, but now we’ve got the object mapping functionality.

Kotlinconf’s app and the Droidcon app both use Sessionize underneath, so porting this part was relatively easy.

Stately

Threading and state are different with native. Stately is kind of a support library for that. It includes expect/actual definitions for Kotlin/Native concepts like ‘freeze’. It includes multiplatform definitions of atomics and thread local objects. It also has collections implemented with atomics, which means you can have mutable collections in frozen state in native.

Others

We’re using a few other libraries in the app, but they’re largely the same from the first version.

Multiplatform Settings

Single-value state containers delegating to SharedPreferences on Android and NSUserDefaults on iOS.

Timber

The Android logging library going multiplatform. This is actually a Touchlab specific fork as native hasn’t been implemented in master yet.

Other Notes

In earlier versions the app had a port of Android’s Live Data to build a reactive data architecture. That “works” but as designed, didn’t mesh well with Kotlin Native’s threading and state model. We’ve replaced that with a new listener structure and coroutines. 🚧That part of the app is definitely still under construction, but should have a more polished version before January🚧.

Future Plans

In the near future we’ll need some internal re-architecture. Adding libraries is nice, but there needs to be a little rethink in how these libraries and coroutines impacts how the components are laid out. That’ll happen over the next couple weeks.

The “Droidcon” app was really intended to be a Sessionize conference app, so we’re going to debrand “Droidcon” and make it easier to publish versions for different conferences using Sessionize to manage their CFP and scheduling.

We’d like to add some new features. Feedback, etc. To discuss. We should do a review of open issues soon and add things that people can contribute.

As new libraries emerge for mutliplatform, we’ll be adding relevant stuff and removing our DIY versions. Once multiplatform libraries are universally publishing with newer versions of Gradle, expect to see a number of useful libraries emerge, as we head into the “production” phase of multiplatform development.


🌿 The weeds: Multiplatform, at least the native side, uses a new gradle dependency feature called “metadata”. As an aside, it would be great if they called it something more google-able than “metadata”, but whatever. Anyway, metadata is not quite at 1.0, so gradle makes no promises about backwards compatibility. Grade 4.7 has metadata version 0.3. Gradle 4.10 has version 0.4. They don’t get along.

🍺 SQLager: SQLiter is intended to be kind of a low level library that will give other libraries pretty direct access to the underlying sqlite3 C api. That’s great, but also means SQLiter can sometimes be a little dangerous and you can get into trouble. SQLager is a companion library currently in development, which both uses SQLiter and is intended to be the opposite. A super safe and easy-to-use SQL access library. You would use this in parallel to other libraries like SQLDelight to get quick and easy direct SQL access without the risk of SQLiter direct access. It’s “Lager” as in you can relax, have a few beers, and write SQLager code. It’ll keep you safe. SQLager is still in dev but coming along. 🍻🍺🍻🍺🍻🍺