Skip to content

Compared with Flutter, React Native and plain KMP

Nobody has heard of GearUI Kit. Everybody has shipped with Flutter, React Native, or Compose Multiplatform. So this page puts the whole stack — GearUI Kit + KuiklyUI + Kotlin Multiplatform — beside the three things you already know, and says where it is ahead, where it is behind, and why.

Two rules for reading it. First, it compares stack to stack: Flutter is a language, an engine and a widget set; React Native is a language, a bridge and a component set; this is a language, a native-view renderer and a component library. Comparing the library alone would be dishonest in the other direction. Second, the stack has two layers with two owners, and every claim below says which one it belongs to. What KuiklyUI does is Tencent's work and Tencent's measurement; what GearUI Kit adds on top is ours, and is only claimed where we have measured it.

The short version

GearUI Kit + KuiklyUI + KMPPlain KMP (Compose MP)FlutterReact Native
Rendering✅ Real native views, everywhereNative on Android; canvas on iOSIts own engine, canvas everywhereReal native views
Native controls — IME, autofill, accessibility, text selection✅ The system's ownReimplemented on iOSReimplemented; a native view must be embeddedThe system's own
Follows OS design updates (iOS 26)✅ The day the OS shipsWaits for a repaint on iOSWaits for the framework to repaintThe day the OS ships
Performance✅ First screen 122 ms vs native 125 ms · SDK 300 KB / 1.2 MB ¹SkikoEngine, MB-scaleJS engine + bundle
Platform debugging tools✅ Every view visible and attributable; on Android, the native ceilingVisible on Android, opaque on iOSOpaque FlutterView; DevTools onlyVisible; two stacks to correlate
LanguageKotlin, shared with the Android team and a JVM backendKotlinDartJS / TS
Default look✅ iOS 26 baseline on every platform, 72 componentsMaterial 3Material; Cupertino is second-classNone
Design consistency✅ Tokens enforced by 23 CI guardsNoneThemeable, not enforcedNone
HarmonyOS✅ First-class targetNoCommunity forkHuawei-maintained fork
Ecosystem and maturitySmall · beta1 (KuiklyUI runs Tencent products at 500 M DAU)MediumLarge · since 2017Very large · since 2015

¹ Tencent's own measurement on HarmonyOS, Huawei Mate 60, complex feed scenario — source.

The last row is bold on purpose. If you do not believe we would concede it, you have no reason to believe the nine rows above it.

Native views: the root of most of the difference

KuiklyUI maps every Compose node to a real platform view — UIView on iOS, android.view.View on Android, ArkUI on HarmonyOS, DOM on the Web (architecture). Flutter paints its widgets onto its own canvas with its own engine. Compose Multiplatform is native Compose on Android and a Skiko canvas on iOS — so on iOS it is in Flutter's position. React Native renders native views, and shares this advantage.

Most of the rows above are consequences of that one fact.

"Flutter doesn't do native controls" is the wrong way to say it, and the right way is stronger. Flutter can host a native view — AndroidView, UiKitView — but each one is an exception with a price: hybrid composition or texture mode, each with its own trade-offs; z-order, clipping, gesture arbitration, keyboard and threading all need handling; and WebViews, maps, video and ad slots are where Flutter apps have accumulated bugs for years. Flutter documents the costs itself (Android, iOS). This stack has no concept of embedding a native view. Every view already is one.

What that buys — KuiklyUI's layer

Pain pointFlutterReact NativePlain KMPThis stack
Native viewsCanvas; native views are embedded, each a special caseNativeNative on Android; canvas on iOS, same position as FlutterAll native, nothing to embed
Text input — CJK composition, autofill, password managers, the system's selection handles and long-press menuIts own EditableText; Chinese IME composition has been a chronic source of bugsNativeReimplemented on iOS, a known weak spotNative UITextField / EditText
Accessibility — VoiceOver, TalkBackIts own semantics tree, bridgedNativeBridged on iOSNative
Scroll physics and system effects — iOS bounce, Android 12 stretch, tap-status-bar-to-topImitated one by oneNativeImitated on iOSNative
Following the OS design language — iOS 26 Liquid Glass, Dynamic Type, dark materialsWaits for the framework to repaint itAutomaticWaits on iOSArrives with the OS update
Platform debugging toolsFlutterView is a black box; DevTools onlyVisibleBlack box on iOSXcode View Debugger, Layout Inspector and Perfetto see the real views
SDK sizeIts own engine, MB-scaleJS engine + bundleSkikoAndroid ~300 KB (AOT) · iOS ~1.2 MB
Incremental adoption inside an existing native appWhole app, or a Flutter moduleEmbeddableYesPage by page — this is how Tencent uses it: 20+ products, 1,000+ pages, 500 M DAU
HarmonyOSCommunity forkHuawei-maintained forkNoFirst-class target

The "follows the OS" row deserves its own sentence. iOS 26 just shipped. Apps on canvas stacks still look like last year until their framework repaints; apps on native views did nothing and got it.

What GearUI Kit adds on top

KuiklyUI is a renderer. It does not ship a component library that looks like a finished product on day one, a design system that stays consistent once ten people are committing, or the runtime plumbing every app otherwise re-solves. That layer is ours.

Components and design system

Pain pointFlutter / React Native / Compose MPGearUI Kit
Looks like iOS by defaultFlutter defaults to Material and its Cupertino set is a painted, incomplete imitation; React Native ships nothing; Compose MP is Material 3iOS 26 baseline, one design language on every platform, 72 components — decided in the spec
Still looks like one product after ten people have committed for six monthsDisciplineSix token scales and 23 CI guards: literals are rejected in component code, a radius can only come from the scale — the guards
IconsFont glyphs, or each app imports its ownPhosphor shipped as image assets under Phosphor's own names, not a font
Platform effects such as frosted glassEach app on its ownA material layer with a degradation rule: where blur cannot run, the surface goes opaque rather than leaving a translucent wash over arbitrary content. We also document where the renderer's blur falls short — publishing our own dependency's gaps is part of being believed

Runtime plumbing

Every row here is a bug we hit and fixed, not a feature we imagined.

Pain pointGearUI Kit
A dialog or sheet gets clipped by the scrolling list it was opened fromThe overlay host sits above the page and escapes any clip
The page underneath an open sheet still scrollsAn overlay freezes the page beneath it; pass-through banners are exempt
Safe-area insets are not reactive in the renderer, and the keyboard's height leaks into the bottom insetA stabilised safe-area pipeline
Tap-outside-to-dismiss the keyboard also fires on buttons and on the input itselfInput regions declare themselves exempt; nothing is inferred from "was the event consumed"
Language packs grow past Android's DEX method limiti18n split by domain; downstream libraries plug into the same pipeline
Wiring it allOne App root: theme, i18n, overlays, safe area, keyboard
Pain pointGearUI Kit
Switching tabs destroys and rebuilds the whole subtreeTabHost keep-alive — janky frames 40.4 % → 4.0 %, measured with gfxinfo on a 1440×3200 device
Swipe backFull-screen, the way WeChat does it; not dependent on the system's edge zone
Android 16's predictive back silently disconnects the legacy callbackHandled
"Discard changes?" before leaving a pageA route-level pending state; BACK ownership is explicit
String-typed routesTyped routes
A sheet can only be closed by CancelGrabber and drag-to-dismiss, tracking the finger 1:1

Debugging and tooling

Three things this stack can do that Flutter structurally cannot, and one honest limit.

On Android it is the native Android ceiling, undiscounted. Kotlin in Android Studio: breakpoints, stepping, expression evaluation, the Profiler, Perfetto, the Database Inspector, Logcat. Layout Inspector shows real Android views, because that is what KuiklyUI renders. This is not "close to the native experience". It is the native experience.

Platform tools see every view. In Xcode's View Debugger and Instruments, in Android's Layout Inspector and Perfetto, every GearUI component is a named, selectable, measurable real view. Flutter is one opaque FlutterView in all of them; performance work has to go through DevTools, and the moment a problem sits on the native boundary — a platform view, the IME, a crash — you are between two toolchains. Compose Multiplatform on iOS is one opaque Skiko view in the same way.

One language, one debugger, one call stack. The app logic lives in shared Kotlin and breaks at the same breakpoint on both platforms. There is no Dart↔native or JS↔native seam; correlating a JS stack with a native one is a React Native rite of passage.

The limit. Kotlin/Native debugging on iOS goes through the Kotlin LLDB plugin or JetBrains' KMP IDE plugin. It works and it is improving; it is not the Android ceiling. Dart debugs the same on both platforms, and Flutter's hot reload is the best in the field. We are not claiming otherwise.

ToolingThis stackPlain KMPFlutterReact Native
Android debuggingAndroid Studio, the native ceilingSameDart debugger + DevToolsRN DevTools for JS, Android Studio for native
iOS debuggingXcode + Kotlin LLDB plugin — works, not the ceilingSameDart debugger, same on both platformsJS + Xcode, two toolchains
View inspector (View Debugger / Layout Inspector)Every real viewAndroid yes; iOS opaqueOpaque FlutterViewVisible
Platform profilers (Instruments / Perfetto) attribute to a componentYesAndroid yes; iOS noNo; DevTools onlyPartly
Cross-platform call stackOne Kotlin stackSameDart + nativeJS + native, hard to correlate
Hot reloadNot verified here, so not claimedYesBest in the fieldFast Refresh
Framework's own toolingKuiklyUI ships an Android Studio plugin (Tencent reports a 40× faster variable inspection, HarmonyOS scenario)DevTools, and it is very goodRN DevTools

Performance

The stack's position is simple: the renderer measures within a few milliseconds of native, and everyone already knows where Flutter and React Native sit relative to native. So the table cites Tencent's measurement for the renderer, states the mechanism for the others, and does not invent numbers we have not run.

MetricThis stack (KuiklyUI, measured by Tencent ¹)FlutterReact Native
Minimum SDK sizeAndroid ~300 KB (AOT) · iOS ~1.2 MBShips a rendering engine; MB-scaleJS engine + bundle
First screen122 ms vs native 125 msEngine initialises, then paintsJS bundle loads, then renders
Page open vs React Native6× faster — against RN's HarmonyOS portBaseline
Animation frame rate58–60 fpsImpeller also holds 60Depends on JS-thread load
Memory+12 MB over a 100-frame animation; near-zero resident overheadEngine residentJS engine resident
System integrationNative views: accessibility, IME, text selection for freeAll reimplementedNative views, for free

¹ Tencent's HarmonyOS measurement, Huawei Mate 60, complex feed scenario (official article; the millisecond, fps and memory figures are read from its charts). SDK sizes from the KuiklyUI README.

Two things this table is careful about. The 6× is against React Native's HarmonyOS port, which is younger than the React Native you know on iOS and Android; dropping that qualifier would be misleading. And the frame-rate row does not say Flutter drops frames — Impeller is genuinely fast. Flutter's costs are startup, size, memory and system integration, not 60 fps.

These are KuiklyUI's numbers, not GearUI Kit's. Our layer is not free. The one number we have measured ourselves: tab switching under our TabHost keep-alive runs at 4.0 % janky frames (gfxinfo, Android, 1440×3200) — down from 40.4 % before the fix, which was our layer's cost and nobody else's. The first person to profile a GearUI page in Instruments will verify this for us; we would rather they found it true.

Where Flutter and React Native are ahead

  • Ecosystem. pub.dev and npm are one to two orders of magnitude larger than anything Kotlin Multiplatform offers, let alone this stack.
  • Maturity and track record. Flutter since 2017, React Native since 2015. KuiklyUI was open-sourced in 2025 — with a real production history inside Tencent, but a short public one. GearUI Kit is at beta1.
  • Hiring, tutorials, answered questions. Not close.
  • Hot reload. Flutter's is the best there is.
  • Pixel-identical UI across platforms. Flutter's canvas gives it; native views do not. For a design-led app that wants the same pixels on every phone, that is a feature, and it is Flutter's.
  • Desktop. Flutter and Compose Multiplatform have it. This stack does not.

When to pick which

This stack when the app must feel native on iOS and Android at once, the team writes Kotlin or shares one with an Android team, HarmonyOS is on the roadmap, or you need to embed cross-platform pages into an existing native app one at a time.

Flutter when pixel-identical UI matters more than platform feel, the team is already fluent in Dart, or you are starting fresh and want the largest cross-platform ecosystem and the best hot reload.

React Native when the team is a web team, the JS ecosystem is the point, and native views with a JS logic layer is an acceptable trade.

Plain Compose Multiplatform when Android is the primary target and iOS can accept a canvas — or as the thing to start with, since everything here runs on the same Kotlin toolchain and adding this stack later is a dependency, not a rewrite.

Sources

GearUI Kit is released under the BSD 3-Clause License.