In this article we investigate the current state of things for the more popular iOS and Android cross-platform frameworks. Read on to get a definitive answer on what each framework can and cannot do, and how they compare.
The ultimate goal of a cross-platform framework should be to enable a team to write a single codebase and deploy it across multiple platforms, sharing as much code — and thus, the theory goes, time and money — as possible. That way we can provide our partners with help on choosing which tool might best support them to achieve their goals.
There are several cross-platform frameworks available, so which are worth comparing to create a fair overview of their current state? The original scope was a technical in-depth investigation of Flutter to gauge its capabilities, pitfalls, and how easy it was to pick up. We did a similar investigation for React Native last year, which was well received. As we started planning we realised that there wasn't an easily digestible, high level overview of the main options on the market today. So we set our sights on creating one.
There are many tools in the cross-platform solutions marketplace:
- React Native
- Progressive Web Apps (PWA)
- Kotlin Native
- ...and several others
Of that list, we picked the two most popular and established solutions on the market, Xamarin and React Native, and the new kid on the block, Flutter.
It's important to set out a fair way to compare these frameworks, not limiting ourselves to comparing them from a technical standpoint to each other and to native code. We looked at each one in terms of backing and community, future plans, satisfaction level of developers, maturity of the platforms, and simplicity of staffing a team.
Of course, we couldn't overlook the technical side. In this case, instead of giving a high level overview, we picked a few areas that we deemed most important when working with these frameworks. The team investigated how well testing is supported, the ease of creating custom UIs and the requirements for platform-specific code and UIs. We also looked at how they deal with native APIs, sensors, hardware and third party libraries and services.
This is not intended as a judgement of these technologies — they each have their pros and cons — but rather guidance about which technology might be best for a project. We find this sort of discussion often stems from a gut feeling, a "shiny object" impulse, or simply from the desire to see if shaking things up improves a tricky situation.
Xamarin is the oldest of the three frameworks at 5 years. It is open source but it's developed behind closed doors and doesn't receive much external input on the code. It doesn't have the best reputation for tooling, stability and performance among mobile developers but .Net enterprise developers seem happy. There is no publicly available Xamarin or Android/iOS specific roadmaps but there is one for
Xamarin.Forms. Being the oldest and only paid for framework reflects well on its exhaustive documentation. It also has a ~4,000 users strong Slack community, plenty of meetups and solid support on Stack Overflow. Finding .Net engineers shouldn't be difficult but sourcing .Net engineers with the necessary native mobile knowledge may prove harder.
Xamarin provides wrappers to several third party libraries, which are generally a great time saver since they're a bit of a pain to create — especially on iOS where there is no automated tool to generate a starting point. Many of these extensions are collected in the Xamarin Components library, where you can find bindings for Play Services, Firebase, Adobe Analytics and several other widely used services. Most bindings are free but some are paid for, e.g., the video playback component. That said, the vast majority of the wrappers have low user ratings, even the ones provided by Xamarin themselves.
Xamarin offers two ways to develop apps. You could decide to create the UI using Xamarin.Forms, a cross-platform port of Windows.Forms, .Net's original UI library (accompanied by WPF over time), or create completely distinct per-platform app modules, in which the only shareable code is the "plain" .Net core business logic.
Due to the nature of Xamarin, you may have an (almost) entirely shared UI code if you use Xamarin.Forms and don't need to provide platform-specific UIs. Forms has no specific feature to present a different UX based on the platform on which it runs, but has some minor degree of integration with native views if it's necessary — it's possible to inject per-platform native views in an XAML layout. This should be fine for minor, ad-hoc integrations but may have issues with scaling.
If the project involves per-platform UIs there is no option to share most UI code and logic, but there is a better ability to interact with native components and APIs. Business logic that can be completely abstracted away from platform details can still be shared.
Xamarin can leverage NUnit, an excellent framework for unit tests that is native to C#. Creating mocks is also easy, which makes the testing side at the Component level comfortable. On the other hand, Xamarin code is split into iOS, Android and possibly Forms; this may require duplicating test code for each platform. On the iOS side, it offers a profiler for checking the performance of the application. This tool is not available for Android.
Xamarin shines when it comes to UI integration tests. A few years ago, Xamarin bought Calabash, one of the leading UI testing frameworks for mobile, and created the Xamarin test suite. This suite is fully featured, robust, and easy to use.
React Native supports the majority of Android and iOS native APIs. Due to its large developer community, even if there is no official API available, there are plenty of 3rd party libraries to choose from. In terms of hardware-specific APIs, React Native lacks a number of them, but again, third party libraries are available. React Native doesn't have official APIs for: Bluetooth, biometrics, NFC, camera and sensors. However, it does have APIs for WiFi and location.
React Native doesn't really offer a drawing API for custom graphics. You are invited to compose existing components whenever you need a custom solution, but it's not trivial to have fully custom drawing without resorting to platform native code. Building simple UIs is fairly straightforward, given that the development team is familiar with React components. If you need to have different per-platform UIs, React Native can manage distinct implementations for Android and iOS. It is possible, although not trivial, to mix and match React Native UI with native UI in the same screen, and it's also possible to have only a subset of an app's screens created in React Native.
Flutter has been publicly available for less than three years but it only started gaining visibility in the development community around a year ago. Flutter is a technology developed by Google that builds upon Dart and a portable C++ engine to implement a reactive UI framework.
Despite Dart not receiving much love in the Stack Overflow developer survey, early blog posts have been positive towards the use of Flutter. Our own exploration of Flutter at Novoda has also been generally positive. There is no well defined roadmap for Flutter but if you look hard enough you can find their current milestones and specific details on what they're working on in this issue discussion. The Flutter team can be found for support in a ~880 user subreddit, ~1200 user Gitter.im, ~740 user Google Group and on Stack Overflow.
Staffing a team won't be easy as the platform is so new and Dart is a niche language, but it can be easily picked up by Java and Kotlin developers. Upskilling an existing mobile team should be easier for Android developers as Flutter can integrate with IntelliJ and Android Studio. iOS developers would need to get used to the language and tooling, which might be a bit more unfamiliar.
Apart from Bluetooth and NFC payments, most hardware and sensor APIs are supported, but some of them are currently in a very early stage of development. A lot of plugins already exist, but some areas are more in flux than others. For example, (at the time of writing) inline video support and dynamic inline maps are still in development, but full screen and static maps are supported.
With performant, custom UI being the main focus for Flutter, the framework is geared to providing a deeply customised UI, which doesn't feel "alien" to users of a native platform. Flutter provides a full UI stack implementation that does not use native UI components, to be able to allow the required degree of customisation, portability and performance. If you want a custom UI for each platform you need to detect the current device and decide which layout to build, which could become extremely tedious. It's important to note that it is possible to embed a FlutterView very easily in a native Android layout, to mix it with native UI in the same screen; this is possible on iOS as well, but this has not yet been documented.
When it comes to testing, it becomes clear that Flutter is a new framework. Dart offers an excellent unit testing framework which can be utilised and Flutter provides you with a great option for testing the widgets on a headless runtime, at unit test speeds. However, running integration tests is somewhat complicated. Lastly, Flutter allows you to run performance tests with their
So, where are we at with the current state of cross-platform frameworks in native mobile development? Xamarin certainly seems to have come a long way since its early stages and has a lot of success stories to support it. React Native has the following of a large community and a few good success stories behind it, such as AirBnb, SoundCloud Pulse and Artsy. Flutter shows some interesting potential, also easily enabling embedding as part of a native UI so it can be added to existing apps and grow from the inside out.
They could all be used in some way to create an app, that's for sure, but could they be used viably for a large scale commercial app? Definitely not yet. Most large-scale success stories for React Native see it being used to implement well defined features and augment a solid base of native code.
What kind of app would you use them for then? Probably short term apps for movie releases, or one-off promotions — Flutter's Hamilton app is a great example. The possibility to apply some of these frameworks for quick prototyping could also be interesting.
Cross-platform frameworks are not a silver bullet. They only work well when used with full awareness of their limitations and strengths, in a context that makes them shine.
The potential difficulties in staffing cross-platform experienced teams is just one factor to consider and shouldn't be overlooked.
The situations in which these tools provide the least value are those in which they are adopted with the misconception that using this framework will fix problems that stem from process or staffing issues.
The many success stories of each of the platforms show that they can prove valuable and effective in tackling specific problems. These instances are usually when there is a competent team working on a low complexity project with no need to reach outside the "safe space" defined by the framework boundaries into native APIs, third party libraries or hardware-driven features.
Are you interested in building an app for your product? Want to get more of our insights on this topic? Contact us to chat mobile and let us help you pick the best technology to achieve your goals.