The Cross-Platform Pendulum Swings Again
Cross-platform development has always been a game of trade-offs. In the PC era, a URL was enough. Then the iPhone arrived, and native apps became the way to deliver mobile experiences. Developers flocked to the App Store for that tiny icon—a gateway to self-built traffic. Soon Android joined the party, and suddenly you had three platforms to support. Maintaining separate codebases for each meant triple the engineers, triple the cost, triple the headaches.
Facebook tried to fix that with React Native. It brought web paradigms to mobile, but performance took a hit as apps grew complex. Meanwhile, Google's Chrome team noticed their browser struggled on phones—long lists lagged, white screens popped up. So they rebuilt the rendering pipeline from scratch, focusing on immediate rendering over concurrency. That became Flutter. Flutter's self-rendering approach promised consistent UI across platforms, but it also created its own performance ceiling.
From Unified UI to Shared Logic
Flutter's core idea is to unify the UI layer. You write in Dart, and it renders everywhere using its own engine. That's great for consistency, but it comes with costs: larger binaries, higher memory usage, and tricky native interop. Plus, Dart hasn't been widely embraced in China, leading teams to explore alternatives like MXFlutter.
Kotlin Multiplatform (KMP) takes a different route. Instead of unifying UI, it shares business logic across platforms. You keep native UI for each OS, but the logic—networking, data processing, business rules—lives in shared Kotlin code. KMP's expect/actual mechanism lets you define common interfaces and provide platform-specific implementations, down to individual functions and properties. That's a finer granularity than Flutter's platform channels, which often involve heavy serialization and can cause jank in high-frequency interactions.
Performance-wise, KMP compiles to native binaries via Kotlin/Native, so it can call platform C APIs directly. In some cases, that yields near-native speed—up to two orders of magnitude faster than bridge-based approaches.
Why Chinese Giants Are Betting on KMP
KMP's adoption in China has been accelerated by HarmonyOS. With three platforms to support—Android, iOS, and HarmonyOS—companies can't afford three separate teams. They need to reuse logic across all three. That's exactly what KMP offers.
Large apps typically split into three domains:
- Performance domain: critical paths like checkout flows demand native-level performance. KMP fits here.
- Dynamic domain: content pages that change frequently (think feed or marketing pages) prioritize flexibility over speed. These often use JS-based frameworks like Lynx or Weex.
- Open domain: super-apps host third-party mini-programs, which have their own ecosystems.
Historically, the performance domain had few options: C++ is memory-heavy, Rust has a steep learning curve, and JS/Dart plateau on performance. Kotlin was promising but lacked infrastructure on iOS and HarmonyOS. Now, with HarmonyOS opening up C APIs and KMP maturing, it's becoming the go-to for shared logic.
Adapting Flutter for HarmonyOS
HarmonyOS has spent significant effort adapting Flutter. Third-party libraries were a major hurdle—by 2025, they'd adapted the top 30 core libraries, with more to come. Beyond that, they optimized Impeller, Flutter's rendering engine.
Impeller pre-compiles shaders at build time, avoiding the 100-200ms jank on first frame that plagued Skia. It also taps into Vulkan for better GPU utilization. On HarmonyOS, this meant smoother frame rates and lower CPU load.
Another win: shared-memory external textures. When passing camera or video frames between Flutter's render pipeline and the native pipeline, they used to copy buffers through CPU, causing stutter. Now, both pipelines share the same memory, virtually eliminating that overhead.
But Flutter still has limits. Each Flutter page can eat ~70MB on a 1080p phone. And Dart's concurrency model restricts memory sharing between threads, so it can't always match native performance.
KMP's Three Key Upgrades on HarmonyOS
Starting in 2025, Huawei and partners rebuilt KMP for HarmonyOS. The first public version shipped in June 2026, with more improvements due by September. Three changes stand out:
From Self-Rendering to Semi-Painting
Flutter's self-rendering means separate GPU contexts, which causes interop problems—like trying to punch a hole in a Flutter view to show native content underneath. KMP now uses a "semi-painting" approach: components generate drawing commands, but they reuse the native render pipeline instead of creating a new GPU environment. This cuts memory dramatically (one Compose instance might need 5 buffers; a page with 10 instances could save ~500MB), speeds up startup, and makes native mixing natural.
CMC Garbage Collection
The original GC on HarmonyOS and iOS KMP was like early CMS: prone to long pauses and memory fragmentation. The new CMC algorithm divides the heap into regions managed by separate threads, boosting concurrency. It also uses stack maps to track object references, allowing objects to be moved during regular GC cycles. Instead of a big stop-the-world cleanup, it's like tidying up continuously—so GC pauses drop from tens of milliseconds to near zero.
Parallel Compilation
KMP builds used to compile all Kotlin into one giant LLVM IR file, which couldn't be parallelized. By splitting it into modules, build times improved 2-4x. The trade-off—larger binaries and lost global optimizations—was mitigated by recording needed symbols and caching global variable info.
AI Coding Meets Cross-Platform
AI is changing how we build apps, and cross-platform frameworks are adapting. Huawei's team is working on two AI-driven tools: A2K (Android to KMP) and D2C (Design to Compose).
A2K reuses existing test cases to help models understand behavior, and it extracts base modules to embed infrastructure, so generated code actually runs in production. Adoption rates have hit ~60%.
D2C initially tried to convert Figma directly to Compose, but failed on layer ordering and fixed offsets. The fix? Introduce React as an intermediate representation. React's declarative model is similar to Compose, and there are mature Figma-to-React tools. Splitting the pipeline into two steps improved scores by 10 points on a 100-point scale, and debugging is easier because you can inspect the React output in a browser.
Which Framework Should You Choose?
React Native is losing ground. Its main value was letting web devs build mobile apps, but AI can now generate native code, diminishing that advantage. Unless you need heavy dynamic updates, it's wise to be cautious with RN.
Flutter still shines for consistent UI across platforms. If you don't care about native look-and-feel and can tolerate the memory overhead, it's a solid choice.
KMP is the strategic pick for anyone maintaining Android, iOS, and HarmonyOS. It reuses logic, plays nice with native UI, and leverages existing Kotlin codebases. Plus, with AI generating code, KMP's unified logic reduces the debugging burden across three platforms.
Ultimately, cross-platform frameworks won't disappear because AI can write code. Instead, they'll evolve to provide cleaner abstractions, better test assets, and tools that AI can use. The future is a hybrid workflow: native UI for platform experience, KMP for shared logic, and AI to boost productivity.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!