Native-only development

TL;DR

Three main reasons:

If you think it is a good idea to use Jetpack Compose (or any other multi-platform UI library like Flutter or React Native) to build an Android and iOS application, it is probably because you’ve never developed or used an iOS application before . . . . It is important to respect UI/UX guidelines of the platform and Compose can’t build an application like SwiftUI does. SwiftUI vs. Jetpack Compose by an Android Engineer

Not all features in the native platforms will be made available through the framework. Some of it might be available later, but then this incurs additional delay to development when using the framework. Besides, as the native platforms continue to deliver new functionalities, the framework will always lag behind. Why Go Native if Possible

Shared code . . . can lead to performance issues, lack of native look and feel, and complications with debugging and tooling. Slack’s mobile developers wanted to work with native language features and APIs, and build best-of-breed apps for each platform . . . . Stabilize, Modularize, Modernize: Scaling Slack’s Mobile Codebases

When cross-platform makes sense:


Source: The Fundamental Problems with cross-platform frameworks

Overview of cross-platform approaches:

Also, except for PWA (progressive webapp), to develop a cross-platform app for iOS still requires use of Xcode and macOS.

Below are additional articles on why various cross-platform solutions have not panned out for their adoptee companies.

React Native

React Native helps Javascript developers leverage their skills into mobile development. React Native uses platform-specific native UI elements to build cross-platform apps. The original architecture has a performance botteneck in the Bridge between Javascript and native API, requires data transfer to be serialized in JSON, and has potential synchronization issue between the Javascript and native modules. Its new architecture (announced June 2018, released with version 0.68 in March 2022) replaces the Bridge with JavasScript Interface that allows JavaScript and C++ objects to reference each other, allowing each to directly invoke methods in the other, thereby removing the performance bottleneck of the old architecture. With version 0.72.0 (Apr. 5, 2023), React Native added caching to text rendering and release a benchmarks app comparing the performance of the old and new architecture. On Android, the new architecture shows 0-8% performance improvements. On iOS, the new architecture shows 13-39% performance improvements.

Articles below discuss why React Native has not panned out for its adoptee companies beyond the performance issue:

Flutter

Flutter is a cross-platform UI toolkit embedded in an “ambient” native app, allowing applications to interface directly with underlying platform servicess. Instead of using native UI elements (widgets), Flutter implements its own, customizing them to mimic the UI elements of each platform, which it then renders using the Skia 2D graphics library. A Flutter app is written in the statically-typed Dart language. The biggest performance issue with Flutter is animation jank, which is especially visible on iOS. Animation jank is caused by Skia having to compile shaders at runtime, rendering it particularly visible on the first run of an animation (see the “Preview: iOS shader compilation improvements” section of What’s new in Flutter 2.2). On August 20, 2022, Flutter announced, along with Flutter 3.3, Impeller, a new rendering engine that pre-compiles shaders and utilizes modern graphics APIs (Metal and, eventually, Vulkan). The first-adopter preview for iOS was made available with the announcement, though Impeller on Android isn’t yet ready for preview as of Flutter 3.7. In addition, Dart is automating bridging to native code/SDKs with FFIgen, for languages following the C calling convention (C/C++, Rust, Go, Swift and Objective-C), and JNIgen, for Java Native Interface binding.

React Native or Flutter?

With the performance bottleneck of React Native and the animation jank of Flutter resolved, the choice between React Native and Flutter for cross-platform development boils down to:

  1. to code in Javascript (Typescript as of React Native 0.71) with the JSX extension or Dart, and
  2. to build using native UI elements for native look and feel, resulting in non-uniform user experiences across platforms; or to build using native-looking Flutter UI elements (widgets) for uniform look and feel across platforms, but potentially non-native experiences on particular platform, such as the use of non-native navigation drawer (hamburger icon) on iOS.

With both Flutter and React Native, the native methods to access the device directly, such as for the sensors, must still be developed natively, in the platform languages.

As of the time of writing, I have not run across any actual performance comparison between the new React Native and Flutter along the lines of these articles:

Progressive Web Apps

Kotlin Multiplatform Mobile

Kotlin Multiplatform Mobile is for multi-platform, not cross-platform, code sharing. It allows for sharing of domain/business-logic code while keeping code to access the physical device (including the screen, for UI) separate and native. KMM helps Android developers venturing into iOS development maintain a common code base. Google itself recently released a multiplatform version of Jetpack Collections (implementing Java collections API) and DataStore.



Source: Kanivets

KMM is most useful in an enterprise environment where the investment in project build process could pay off over time and across projects and on apps where the business logic largely resides on the front end with heavy client-side persistence and offline support:

Additional frictions on the iOS side of KMM deployments have been reported by multiple sources:

Compose Multiplatform

While KMM is for sharing domain logic, Compose Multiplatform (CM) allows sharing of declarative, reactive UI. It’s built off Google’s Jetpack Compose with UI rendering done using the same Skia 2D graphics library powering Flutter (Skiko). For the Web KMM can also use DOM syntax (no code sharing then?). Compose for iOS is now alpha (Apr 2023) but does not yet provide built-in support for requesting runtime permissions or tracking geolocation and biometric authentication (still doable, but not production ready?). Further, in SwiftUI vs. Jetpack Compose by an Android Engineer, the author argues that, “It is important to respect UI/UX guidelines of the platform and Compose can’t build an application like SwiftUI does.”

Multiplatform development relies in large part on managing the build processes of codes for multiple platforms. This is true in the case of both KMM and CM. For the course, do we want to focus on finagling the project build process or do we learn native platform development, which both KMM and CM (and Flutter and React Native) also depend on?


Prepared for EECS 441 by Sugih Jamin Last updated: May 14th, 2023