109

Multiplatform native development in Kotlin. Now with iOS!

 6 years ago
source link: https://blog.kotlin-academy.com/multiplatform-native-development-in-kotlin-now-with-ios-a8546f436eec?gi=5ff4d7a4ba84
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Multiplatform native development in Kotlin

This article was updated on 25.11.2018.

Imagine that you don’t need to implement the same features for Android and iOS separately. Now imagine that you can reuse this code on Web. Just to push it a bit more, imagine that you can even share parts with a backend, for instance, API definitions, utils or DTO objects. Well, you can and you don’t need to write anything in JavaScript. You can implement all clients natively: Android in Kotlin and iOS on Swift. You just need to use Kotlin multiplatform capabilities.

If you prefer watching, here is my KotlinConf presentation where I talked about this topic.

JetBrains presented two applications to demonstrate Kotlin/Native possibilities:

  • Kotlin app (Play, iTunes, Github) — is a real multiplatform application! Server-site is in Kotlin/JVM, Website in Kotlin/JS, Android in Kotlin/JVM and iOS in Kotlin/Native. Every module is written natively.
  • Spinner app (Play, iTunes, Github) — is demonstrating possibilities of Kotlin/Native. It includes server, iOS app and Android app. Everything is in Kotlin/Native! Yes, it is possible.

The progress, that Kotlin/Native team made, is really impressive! Both applications are a huge step forward and both are presenting two powerful approaches. I believe that after this presentation people will treat more seriously my postulates about independence between platform and business logic.

In this article we are going to concentrate on first approach because it is more mature and I think that it might be soon used in commercial projects. Imagine a company that already have well designed Android application and wants to have its iOS equivalent. It might soon find out that applying this approach is the simplest way. They would have all business logic already written and tested. They would only have to write iOS views and repositories. This is, in well designed application, minority of the work.

How does it work?

Multiplatform Kotlin project is composed from different types of modules. Kotlin specification defined following types of modules:

  • A common module contains code that is not specific to any platform, as well as declarations without implementation of platform-dependent APIs. Those declarations allow common code to depend on platform-specific implementations.
  • A platform module contains implementations of platform-dependent declarations in the common module for a specific platform, as well as other platform-dependent code. A platform module is always an implementation of a single common module.
  • A regular module. Such modules target a specific platform and can either be dependencies of platform modules or depend on platform modules.

(descriptions from specification)

How does it look in practice? Let’s analyze KotlinConf application.

1*8NLntZdpf__KTqWhI15nxQ.png

Folders on root of kotlinconf-app

We can find:

  • Single common module which is used by all platforms
  • Additional common modules for JS and JVM
  • Platform modules for iOS, Android, Backend and Web

Let’s analyze them one by one.

1*M5erAXyih6ctSqcIW35ZjQ.png

Modules dependency structure in kotlinconf-app. Diagram made in https://www.draw.io

Common modules

KotlinConf application common module includes elements that are shared between all modules. First thing we can find there is a data model. It is already a big value to have it defined in common module instead of having it defined in 4 separate modules for 4 different platforms:

1*IATgkBmtsZJxTwldKq6Cwg.png

Another thing that can be found there is a set of tools for Date representation:

1*NaZryUZ1mRI1ESHjxPQn8A.png

Note that this code contains logic, and since it is placed in common module, it can be used in all platforms. Another important thing to note is that Kotlin does not have its own Date representation. Every language have different objects used to represent date and time. This is why Date needs to be defined in common module as expected declaration:

1*1-aXLLvFYKJrFhDEbUIjIA.png

Date.kt file from common module on kotlinconf-app

expect keyword means that such element needs to have actual implementation in every platform module that depend on this common module.

Noticed rhombus next to expected declaration? You can use it to navigate to corresponding actual declarations.

In this case, actual Date declaration does not depend on specific platform, like Android or iOS, but instead on programming language. While both Android and Backend are in Kotlin/JVM, it is reasonable to make module which will provide actual declarations for both of them. This is how common-js and common-jvm modules were defined — to provide language specific Date actual declarations. Both modules contains only single file with actual declarations that corresponds to expected declarations in Date.kt file.

1*CfRWqhLXZLAWKhKSEsoUCQ.png

JvmDate.kt file from common-jvm module on kotlinconf-app

1*liRYBiCqENmuDoCBlGDIiw.png

JsDate.kt file from common-js module on kotlinconf-app

Android, Backend and Web

Android module depends on common-jvm and thanks to that it can use data model objects and Date from common module. It is normal Android project even though it contains lot’s of innovative Kotlin approaches like:

Note that while Anko is used, there is no layouts defined in the Android project, so more code can be written in Kotlin instead of xml.

Backend is developed in Ktor framework. It depend on common-jvm module. It is pretty short while Ktor is quite minimalistic and this backend logic is not complex.

Website is developed using Kotlin/JS and React framework. It means that instead of HTML, all view elements are defined using Kotlin DSL. Website represents different logic than Android and iOS app while it is used to display live information about the voting process. It connects to the server using WebSockets. This connection is used to receives updates on votes for the given session.

iOS implementation is definitely a point of interest on this project. I must say that I cannot arbitrarily describe how it works, but let’s describe some elements that we can find in this module.

First of all, project is using iOS libraries. They are located in Frameworks folder.

1*_yILn07g7RDK1bFtZWRaOw.png

ructure of ios module on KotlinConf-app

You can easily find their usages around the project. For example, here is an OMGHTTPURLRQ usage:

1*hTuyhcaltuTrUdF0Mbs0wA.png

It is function, written in Kotlin/Native that is used to get votes from API. It is using iOS library called OMGHTTPURLRQ.

About view definitions, we can find storyboard files (xml files that are describing how view looks like). They, together with images, are located in konan folder.

1*dD9KZv8_WYeqPyPBWudlNw.png

Business and presentation logic are defined in Kotlin under src/main/kotlin. It is readable for people who are familiar with Kotlin, iOS and used libraries.

1*cIsx8RDKbbJK8hfSeVfm8w.png

1*O1uvVX7ObbmLbb__N9eBKw.png

Conclusion

After all, I am really impressed in maturity of Kotlin/Native, although project analysis is not enough to jump into iOS development in Kotlin. Especially that project lacks user guide and all its iOS configuration files are quite scary. But after all you can see that applied approach is really mature — we can use iOS libraries and elements like storyboards or imagesets. Therefore, solutions that were developed in iOS can be used here too, and iOS developers should be able to quickly move to Kotlin/Native. Today (4.11.2017), I wouldn’t start writing iOS applications this way, but I am starting new Android project and I decided to define common module in which I will keep all cross-platform elements like data model, use-cases, presenters, interfaces for views and repositories. This way I will be able to easily add iOS application when I decide that iOS development in Kotlin/Native is mature enough for using it. Looking at its current development speed, I think that it will happen pretty soon.

About overall structure, I think that multiplatform development is giving much bigger common code extraction possibilities. While iOS and Android apps have similar business logic, I would expect it to be located in common module. Common module could also declare interfaces for network and database repositories. With good design, it might include network API usage and database calls. Should it all be presented in this application? It does not need to. Application supposed to show possibilities of multiplatform Kotlin development and it satisfies this goal perfectly. Kotlin team is already really busy so good architecture for multiplatform development is something that can be proposed by us, Kotlin community.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK