Overview of KotlinConf 2019

Anatoliy Varyvonchyk
Bumble Tech
Published in
14 min readFeb 6, 2020

--

I’ve been developing with Kotlin for the past two years, and when I was asked if I’d like to attend KotlinConf 2019 with some of my colleagues, my answer was a great, big Y-E-S!

Having the chance to attend what is one of the best conferences for mobile devs, I really want to share with you all my overall experience, impressions and feedback from the talks that I attended.

There were 4 different tracks of talks so obviously I couldn’t go to them all, so do check out any of the topics that interest you and that are not covered here. Hopefully, this should make you want to check out the others on JetBrainsTV channel and why not come to the 2020 one? :)

Foreword

To give you an overview, the conference is splitted in three days: two of talks and one of workshops. The conference was held at the Bella Center, which is a large business centre with a hotel and conference venue, accessed by covered walkways — very convenient given the inclement weather.

On the workshops day I had to choose between 5 topics — the most trending ones get snapped up very quickly, so, if you are planning to go this year, try to get your ticket as early as possible here.

During the conference we had plenty of talks to choose from as all 4 tracks took place at the same time. On top of that, there was a dedicated space in the main hall where you could do code labs based on the material shared in the talks.

Let’s get started!

Workshops

I attended the ‘Kotlin in Android’ workshop. This workshop consisted of 4 parts which were practically independent of one another:

  • Coroutines in Android
  • Advanced coroutines in Android
  • Jetpack compose
  • KTX libraries and Multiplatform

The first part covered the basic concepts of coroutines, dispatchers, scopes, error handling and cancellation. The example used was a small application which makes network requests, displays the result, progress and saves data to a local database. The entire code is very much tied to Google architectural components: LiveData, ViewModel, Room.

Overall, quite well-known and basic principles are explained, but if you already know something about coroutines, you won’t discover anything new. You can find the project at google code labs.

Advanced coroutines in Android introduced and then demonstrated the use of flow.

Jetpack compose — codelab was used as an example. This covered basic concepts, and, once again, there wasn’t anything new or unusual for those with even a limited knowledge of the subject.

KTX libraries and Multiplatform

Android KTX is a set of Kotlin extensions, whose purpose is to provide idiomatic Kotlin code and improve Java API. For this purpose, language tools are used a lot: function and field extensions, lambdas, named parameters and coroutines.

During this workshop the presenter talked in detail about the right way to write your KTX wrapper over a Java library in order to make it idiomatic from a Kotlin point of view. He shared several insights about how he wrote KTX versions of libraries and what complications arose. The example he gave us was to implement a project, migrating Android Location API to Kotlin Flow.

Multiplatform is one of the main trends this year. The task was to implement a Sudoku application, exporting all the shared logic to a multiplatform module and saving a separate UI for various platforms.

Apart from the 4th part, I was a bit disappointed by the overall workshop.

I feel that we could have spent less time talking about the basic concepts and links to the code labs and gone deeper into the examples or used more complex examples. I understand that maybe their intention was to get everyone onto the same page but I feel that this could also have been achieved by sending those links out beforehand. Feel free to share what you think about this in the comments section.

Talks

Opening Keynote by Andrey Breslav

The keynote gave an overview of the history of Kotlin and its likely immediate future.

Kotlin is being tried and used increasingly across the world. Version 1.0 was tried by 200,000 people, version 1.3 by 4,000,000 and the trend is only growing, because the Kotlin developers are trying to make the language convenient to use in various fields, including data science.

Here are its application areas at the present time:

  • Server development: Spring boot, Web MVC, Web Flux and Ktor
  • The Kotlin Android-First language officially supported by Google. It is already used by 53% percent of developers and 60% of the top 1,000 applications on the market have been written using Kotlin.
  • Multi-platform development. Quite large companies are already writing applications reusing the business logic between Android/IOS: Yandex Disk, Yandex Maps, PlanGrid, Planboard, Cash App, Quizlet and VmWare Workspace ONE. In future the number of these applications will only increase, not only because it is interesting/trendy but it brings immediate business benefits.

Spring 2020 will see the launch of Kotlin 1.4. The team has focused on increasing quality and productivity levels, and the latter has produced results which can already be seen in version 1.3.60. Specifically, the speed of Gradle import increased by about 2.5 times while requiring about 75% less memory, while code completion operates about 3 times faster.

Source: From presentation by Andrey Breslav at KotlinConf 2019

So, what can we expect from version 1.4?

  • The development team is working on a new compiler for speeding up project building. Part of it will appear in version 1.4, the rest a bit later. For example, the front-end compiler (I am not talking about JavaScript, but rather about the first steps in compilation: code parsing, name resolving, type checking and other steps. This part of the compiler also works in the studio and represents a bottleneck, where kotlinc spends the most time). In terms of internal metrics, it is now 4.5 times faster.
  • Unifying back-ends. 3 compilers are now represented: Kotlin/JVM, Kotlin/JS and Kotlin/Native. For historical reasons the first 2 compilers were written separately, and practically did not reused code. After work began on Kotlin/Native the infrastructure was changed and intermediate representations (IR) were implemented, which basically use the same approach as bytecode in virtual machines. At the present time Kotlin/JVM, Kotlin/JS compilers are migrating to a new approach which will make it possible to reuse code shared between back-ends.
  • As a result of the previous point it will be possible to write multi-platform compiler plug-ins. Unfortunately, the API in 1.4 will not be public, but JetBrains is actively working with Google, because they already use a compiler plug-in for Jetpack Compose.

Additional multi-platform updates expected in 2020:

  • The option of running IOS applications from an Android studio! The development team is working on a plug-in with closed-source code. This will give Android developers a convenient option for running, testing and debugging Kotlin code on IOS devices and simulators.
  • We are also expecting options for running Kotlin code on watchOS and tvOS.

There are also plans to introduce new features to the language, but just a few because the main focus of 1.4 is optimisation and tuning.

For a more detailed preview of the keynote visit the official site.

Ktor for Mobile Developers: Fear the server no more! by Dan Kim

The next talk I went to was on Ktor and how to use Kotlin on a server.

Dan Kim suggested using Ktor when you need a lightweight server able both to aggregate data in a way convenient for the client, and to gather useful information.

During the course of the talk the following technologies were used in creating the project.

  • Ktor
  • OAuth2
  • Retrofit
  • Moshi
  • Google APIs
  • Google Cloud

Ktor may be used along with any popular container: CIO, Jetty, Netty or Tomcat. This particular project used Netty.

To run Ktor we use the main function everyone is familiar with:

Launching ktor server

The main location where incoming queries are handled is Application, which is a subclass of the Pipeline class from Ktor. After a query is received via HTTP, HTTP/2 or WebSocket, it is transformed in ApplicationCall and passes along the pipeline, which is configured in Application. The pipeline itself consists of one or more interceptors providing routing, compression etc., after which handling is completed. The module in question also needs to be registered in an application.conf file.

Example of main function

After this Dan demonstrated how you can extract data from a query and use it for carrying out another query vis-à-vis a public API. The example was then expanded by using Oauth2 authorisation along with Ktor, which makes it easy to require authentication for the necessary queries.

For deploy purposes GoogleCloud was chosen. For more detail as to how to do this, watch here.

To sum up my impressions of the talk: if you need to roll out a non-complex web server and you’re unfamiliar with server development, but familiar with Kotlin, it won’t take you long, because progress is quite straightforward and is described in detail in the guides.

Coroutines! Gotta catch ’em all! by Florina Muntenescu & Manuel Vivo

This talk covers coroutines, their cancellation and handling exceptions.

The key concept when working with coroutines is `CoroutineScope` which acts as a trigger point and offers the option of cancelling, managing and building a coroutine hierarchy.

Let’s take a look at this example:

Coroutine example

We see the CoroutineScope function has the parameter Job(), which allows us to track the life cycle, cancel or flag up errors.

The Job life cycle consists of the following steps: New, Active, Completing, Completed, Cancelling and Cancelled. Although developers do not have direct access to these states, they do have access to the public fields: isActive, isCompleted and isCancelled.

It is also important to mention CoroutineContext which, besides lifecycle, has parameters as to which thread the work will be performed on and how error handling will be implemented. The configurations have default settings and new coroutines inherit the parent context, which is very important for handling errors and cancelling coroutines.

We developers usually use scopes which, on their own when the right time comes, call cancel(), and so that’s something we don’t have to worry about (for example, ViewModel.viewModelScope). If, however, you perform this manually, it is worth also making sure that this is actually the case. For example, we are considering code which waits for a second while two elements are typed in the coroutine, and then completes the operation.

Cancelling coroutine

In actual fact, after ‘Done’ has been typed, we see ‘Hello 3, Hello 4’. And, only after this, does the coroutine change to the cancelled state. We have to add a little bit of code manually ourselves to prevent this from happening.

There are several mechanisms for doing this:

  • job.isActive — checks whether the current coroutine is active; in our case after calling ‘cancel’, the state changes to ‘Cancelling’
  • ensureActive() — does the same thing as in the first point and immediately flags up CancellationException, which interrupts the operation
  • yield() — returns the thread of the current coroutine dispatcher to the other coroutines to run, after which it also checks the state of the coroutine and flags up CancellationException

For it to work as expected, all you need to do is replace while part with one of the following options:

  • while (i < 5 && isActive) {
  • while (i < 5) {
    ensureActive()
  • while (i < 5) {
    yield()

Moreover, rewrite the coroutine slightly and everything starts working for us:

Example of delay function

This is because the cancellation mechanism has been implemented for the delay() function.

As you can see, lots of minor details need to be understood if coroutines are to be used correctly.

The talk goes on to explain how and for what purpose join() and await() can be used and, in the second part, how error handling works: how certain errors can be suppressed at the parent level, the difference between errors and CancellationException and how they are handled.

The talk is detailed and interesting. If you plan to write and use your own scopes in real applications, you’ll find watching it very helpful.

Kotlin Native Concurrency Explained by Kevin Galligan

Kevin Galligan begins by reminding the audience that extensive discussions have already taken place on the use of coroutines between different threads and that a draft version as to how this will be implemented has already been presented, however this subject will not be covered at all.

The use of multi-threading in Java is very complicated and has a lot of problems associated with it, therefore it was decided to use another approach in Kotlin/Native, so the developer had fewer opportunities to make mistakes. There are several rules which need to be followed in Kotlin/Native.

  • Mutable state is only available to one thread (mobile developers came across this concept when trying to change the UI using any thread other than the main thread)
  • Immutable state is available to many threads.

The main class for working with multi-threading in Kotlin/Native is Worker. The nearest equivalents are ExecutorService, Handler, MessageQueue and Looper. It works in exactly the same way: Worker contains a queue of tasks, to which you can send a task to be executed. And there is a private thread, available for the current Worker. While it is working, it takes tasks from the queue and executes them on the private thread.

Let’s take several examples:

Using worker

The signature for the `execute` method looks like this:

Execute function

T1 -> input parameter, T2 -> output parameter.

The first parameter of the function is enum, which can accept one of 2 values: SAFE or UNSAFE. The second value allows you to ignore the two main rules described above, and it is strongly recommended that you don’t use it.

The second parameter is a function which returns the incoming parameter for performing operations. Kotlin/Native runtime handles this function and ensures that the result may be transferred between threads. And we must use the lambda here and not simply the argument, otherwise straightaway we will have broken the first rule vis-à-vis transferring an argument between threads.

The third parameter is a function in which the main useful work will take place on another thread. As a result, we obtain Future which we can call later and obtain the result T2.

Let’s see if we can try to transfer a parameter to a function:

Transferring parameter

When we try to do this, we get an error: kotlin.IllegalStateException: Illegal transfer state

When using this method, we still have another thread which calls the main function and it contains links to the someData variable. Even though the object itself is immutable and neither of its arguments change, this is nevertheless insufficient for Kotlin/Native to recognise it.

This is why the .freeze() method exists, which makes an object completely immutable (frozen) at a memory level, goes recursively through the object and also makes all objects completely immutable. After this, the object can no longer be returned to a non-frozen state. And, after this, it will be possible to use this object between threads.

In order to fix the previous example, all you need to do is call this method:

This leads to several conclusions:

  • By default, global objects will be ‘frozen’ because you can potentially call them from any thread.
  • Since in complicated cases it might not be clear why an object has become ‘frozen’, there is a special function: ensureNeverFrozen(). This flags up an exception if an attempt is made to make this object immutable and you can track where this originated from.

Kevin goes on to talk about Atomics, giving an overview of what coroutines are in multi-thread Kotlin/Native. And he mentions libraries which today are already using a new model of multi-threading in Kotlin/Native:

The Compose Runtime — Demystified by Leland Richardson

I need to say a few words before proceeding to the talk overview. This talk is quite deep and if you’ve never heard of Compose it will probably be difficult to follow what is actually happening. But if you’ve already played with Compose or listened to some talks you should find it both interesting and useful.

The nature and state of ‘Compose’ at the present time:

  • Entirely new declarative Android UI Framework (inspired by React/Flatter)
  • Written 100% in Kotlin
  • Created by the Android UI Toolkit team
  • Uses Kotlin compiler plug-in
  • Not tied to Android releases
  • At the Developer preview stage

The main reason for creating a new UI framework on Android was the huge amount of legacy in existing codebase (open View.java and you’ll find over 20,000 lines of code). Also, as a bonus new approach where you are building a complex UI component based on collections of smaller ones, it is much simpler and easier for everyone to understand. In terms of efficiency, one of the goals was to be able to make a lot of updates of the actual content and invoke only those functions where the UI need to be updated — that’s the part where compiler plug-in helps.

Leland Richardson goes on to give an example of the distinction between a declarative and an imperative approach when implementing the UI. In the imperative approach we are usually reacting to changes and update only the appropriate part of UI. Using the declarative approach, we render UI based on the full and complete state of what we actually need to show the user. In summary, the declarative approach allows you to render the UI using the full state of what we need for rendering it, while leaving unchanged some small parts of the UI depending on minute bits of information. This means we are not dependent on the previous state.

Here’s a small example:

Composable example

BadgeEnvelope accepts ‘count’ as an input and uses other @Composable functions for building the UI: Envelope and Badge.

The @Composable annotation can be compared with the suspend function. The suspend function can only be called from another suspend function; in exactly the same way the @Composable function can only be called from another @Composable function. And in exactly the same way that the suspend function uses the call context (and, if called from another suspend function, the context of the parent function is used), the @Composable function also uses a special contextual object, which is passed down the call tree of the @Composablefunctions.

The @Composable function represents an ordinary function, with two differences:

  • Equivalents of last call ‘memory’ (positional memorisation)
  • May be called at any moment in time (recomposition)

These 2 points together allow, in runtime, to understand which exact sub-part of the UI need recompositions and calls only that part.

The framework developers have generally assumed changes to the UI structure will be infrequent. The values of the transferred parameters may change often but not the actual structure of the UI elements.

The author of the talk goes on to speak about: the internal workings of how to achieve optimisation and improve productivity; how slot table (an internal mechanism for skipping some computations and render only what is actually needed) is used for storing results of calling functions; and how optimisation occurs, if you call the @Composable function with a large number of constant parameters.

The talk also touches on the future a little. He speculates around which additional optimisations might be developed and improved; how pure @Composable functions are; and how, potentially, in the future it will be possible to perform some functions in parallel, and which calls might be able to be omitted and why.

If you’re already familiar with Compose and have seen talks on it, I think you’ll find this one very interesting, particularly as it is about how things stand in terms of internal implementation.

Conclusion

A few more talks merit a mention:

What’s new in Java 19: The end of Kotlin? — In this talk Jake Wharton shares on the development of the Java world, about functionality that already exists now and what plans there are for future development.

Kotlin Puzzlers — One of the most entertaining talks, this was its third time running (obviously with new tasks to solve). If you think you’re a Kotlin expert and understand any code, check out this talk and maybe you’ll think again.

Besides the talks themselves, there were company stands such as JetBrains, Google and many more, where you could talk to their expert developers and ask questions, not something you get to do every day.

KotlinConf is a lot more than just an event with a lot of talks, but rather it brings developers together from around the world, all with shared interests. It’s a great chance to meet each other and share knowledge and experience.

I really wish I could have attended all the talks in person — it would have taken a lot longer than just two days, for sure. Thankfully, though, all the videos are now available for everyone to watch — check them out here.

--

--