· 3 min read
arst
The myth of cross-platform efficiency
Cross-platform has never been, and still is not, “two apps for the price of one”.
Two Apps
This issue should be obvious. You don’t get two native apps. You get two good enough apps. If those two apps are indeed good enough, this isn’t really an issue. However, cross-platform proponents have often implied that the basic 2-for-1 equation. Practical reality falls quite short of that.
Price of One
Non-trivial apps always require features and integrations that are more efficient when they are built native. Cross-platform tools attempt to homogenize the specifics of Android and iOS, but they can only do so much. At the end of the day, an app runs on a real device.
Some native platform integrations are simply different. Not just the API, but the flow and constraints in how they are implemented. No cross-platform tool (even KMP) can entirely avoid this. This factor will always make “1” into something larger than “1”. Specific cross-platform tools, and how well directly they interface with the native platform, can impact how much larger “1” is. Because Compose and KMP were designed to interact directly with native platforms, they can minimize that impact.
UI is another issue. For performance reasons, some complex UI will struggle with a cross-platform implementation. That varies from framework to framework. However, some UI components have native implementations available. Trying to rewrite them with cross-platform UI is simply not an option.
For example, maps. These are complex, performance-critical components, that have native implementations. Obviously writing a cross-platform map UI from scratch would be a terrible idea. You need to integrate the native map implementations into the cross-platform tool.
All modern cross-platform tools provide some mechanism to integrate native UI. However, the overhead and difficulty involved varies significantly between cross-platform tools. Again, because Compose and KMP were designed to integrate directly with the native platform, no other cross-platform tool could possibly be better at doing this. Both from the perspective of developer effort, and additionally the runtime performance of the integration.
Other cross-platform frameworks don’t just hide the native platform. They remain removed from it at a technical level. In technical terms, calling the native platform is an RPC (Remote Procedure Call). Although the target of the call isn’t “remote” in the sense that they live in the same process sandbox, the calls need to be made between incompatible runtimes. Data needs to be serialized, and often calls are made through message passing.
In less technical terms, most cross-platform frameworks don’t play well with others. They are their own world. Communication outside of that world is a strict process that involves overhead.
Compose and KMP operate directly within the native app runtime. In the case of Android, again, Compose and Kotlin are the tools you would use for a fully native app. For iOS, Kotlin is presented to Swift as if it was just more Objective-C or Swift (use SKIE, btw). Native calls aren’t RPC calls.
With Compose Multiplatform
A cross-platform app is not “2” native apps, and it costs more than “1” to build. With Compose, the Android app is actually native. On iOS, how native you want the app to be is flexible. You can expend more effort, and get closer to native, or not. Because of how KMP and Compose integrate with the native runtime, while you can’t have “1”, you get as close to “1” as possible.