Engineering Manager Framework: How to Evaluate Mobile Multiplatform Solutions

The following text is transcribed from our Kotlin Multiplatform webinar. There is a video at the bottom of the blog post if you would rather listen to the segment. If you find this segment interesting, you can register for the full webinar recording and slides here


Slide 1

This diagram. Here’s where we find out what Native really means, and, even simplified, there’s a lot going on here.


This input category is how the app developer writes the app. A Native Language isa language officially supported by the platform. Swift and Objc on iOS, Kotlin and Java on Android, HTML/CSS/Javascript on Web. An Other Language is a language like JavaScript on mobile, or ClojureScript on the Web. It also includes WYSIWYG visual programming interfaces that some no-code multiplatform solutions use.

The Process category is what the build chain does to the input in order to create an output. I mentioned Cross-Compilation and Trans-Compilation earlier.

But to clarify both of these, cross-compilation here is when a high level language is compiled directly to the native code for each various platforms before outputting the final product. This is called Ahead of Time compilation or AOT for short.

Trans-compilation here is when a a high level language is compiled to a another high level language which can then be fed back as input to another process, usually to a language native to the platform that can then go through the native build-chain.

Runtime here includes things external to the platform that implements portions of an execution model needed to execute the app like virtual machines, interpreters, and necessary libraries.

The Outputs category determines the type of app generated. Native Code is the low level code executed natively by the platform. Native code generates Native apps. A Native Container bridges web technologies with platform specific technologies by running web code in a webview on the native platform. A native container plus web views generates Hybrid apps. As mentioned before, a Native Language needs to be processed again to become a mobile app. But, it could also create a Web app if the output language is JavaScript or Wasm.

Once I put this together, I searched through documentation looking for how different tools worked and fit them into this model. I’m going to talk specifically about Ionic because it is a Hybrid solution, but more importantly, I’ll talk about React Native, Xamarin, and Flutter because they are so popular and, of course, I’ll talk about Kotlin Multiplatform because that’s why we’re all here. One last thing before we move on. Notice how this starts to explain some of the negative feelings we have about cross-platform solutions. For any solution, If we need to code in a new language, it will slow developers down. And, If there is an interpreter or VM between code being asked to run and code being executed, it’s going to slow the app down. And for hybrid solutions, a webview is fairly heavyweight and will slow things down even more


Slide 2

Ionic is a popular Hybrid app development tool built on Apache Cordova. You write your app in standard web technologies; the runtime includes widget libraries and native platform interop libraries, then, everything is wrapped in a native container and you get a hybrid app. Now, the web and mobile are different. On mobile you need to handle things like the offline experience, the application lifecycle and back button expectations. Hybrid solutions promise to make things easy, but you actually need to work really hard to make a hybrid app meet native expectations. 


Slide 3

React Native takes something that worked really well on web (that is, react) and makes it work on mobile better than hybrid apps. You develop mainly in Javascript and the runtime provides native or native-like widgets along with tighter interop with the underlying platform. Native code is output at runtime by the JavaScriptCore interpreter which allows the app to be categorized as Native. The differences between web and mobile are still issues to consider, and it’s easier to meet native expectations with React native, but it’s still difficult. For example, one of the problems mentioned by both Airbnb and Udacity is the 3 platform issue: to make their React Native apps more native, they had to deal with the javascript bridge and code independently for Android and iOS. This was more of a pinpoint than expected and they needed to do it more often than expected


Slide 4

Xamarin was one of the first to focus on sharing business logic with native code across platforms. It was quite a bit later in Xamarin’s life that they introduced Xamarin.Forms to share UI as well. You write your code in C#, and it gets processed to include the .NET runtimes. On iOS, it is all compiled ahead of time because iOS doesn’t allow 3rd party execution engines on Android. The Mono VM is included in the distribution so it can just-in-time compile native code at runtime. AOT is generally faster than JIT and benchmarks do show Xamarin.Android is significantly slower than Xamarin.iOS


Slide 5

The Flutter solution is yet more native because it AOT compiles on both Android and iOS. You write your app in the Dart language and, for dev builds, the Dart VM will JIT compile, but for production builds it will AOT compile all the necessary run-time libraries for widget rendering and business logic directly to native code. 


Slide 6

Kotlin Multiplatform is the most native solution yet. It is first-class for developing Android apps. Kotlin is already the best for this and fully supported by Google. Flutter is not first-class for developing Android apps until Google puts a lot more money into it and commits to it because they will need to sustain both the Material Widget library on Flutter and the standard Android widget library. Neither Xamarin nor ReactNative will ever be first-class for developing Android apps. It AOT compiles on iOS to a standard Objective-C framework which is already first-class on iOS and, even though Swift is becoming more popular, Objective-C frameworks are still prevelant. ReactNative is difficult to use in existing apps. Xamarin is impossible to use with natively developed apps. Flutter is working on it.

And that’s a huge difference: Kotlin Multiplatform is about optionally and easily sharing code. ReactNative, Xamarin, and Flutter are foreign ecosystem with a disconcerting amount of vendor lock-in. Kotlin Native also outputs to JavaScript or Wasm for sharing code with web. It’s more difficult than it should be to share React for web and ReactNative, but there is a way. Xamarin isn’t officially supporting web output yet, but people are trying. This model is quite good and this is how most people approach the definition of native, even if they haven’t thought about it as deeply as this. Often it is simplified to just the final App Types, with Web being on one end of a spectrum, Native being on the other, and hybrid filling out the in between. 


Recording: Webinar Segment


The video is from our Kotlin Multiplatform webinar. If you find this segment interesting, you can register for the full webinar recording and slides here