TL,DR: Uno platform is everything I hoped Xamarin.Forms would be. In light of this, please tell me why one should bother with .NET Maui.
In 2012, I heard of this new platform called Xamarin. At the time, it was pitched as a rebranding of Mono (C# for the masses) with an emphasis on iOS and Android. As a small developer, maintaining multiple, redundant code bases was (and still is) my biggest pain point — so I was interested.
In 2013, I paid a good friend of mine to take a deeper look. He created some benchmarks (launch time, rendering time, etc.) for apps that were a lot more real world than anything found in the Xamarin marketing. The iOS performance was great. Android — not so much, but tolerable. There were promises to make Android better so, we decided to take the leap and build a few apps.
Then, in 2015, Xamarin.Forms was making enough noise that I thought I would give it a try. Even though Xamarin allowed us write the business logic once, that was only only a fraction of the effort to build our apps. The Xamarin.Forms elevator pitch was “one code base for all devices”.
However, I quickly learned that there were more than a few problems with Xamarin.Forms.
First, Xamarin.Forms’ philosophy at the time was “make iOS apps look like iOS apps and Android apps look like Android apps”. In other words, they knew it was going to take a lot of work to normalize the UI so they were not going to bother. If you wanted consistency between platforms, you were going to have to pay for it in sweat.
Next, a lot of what I was used to in Android and iOS just wasn’t in Xamarin.Forms’ abstracted UI. Some examples.
- 9-Patch images
- SVG image
- long press gesture
- custom fonts
- multi-resolution / multi-platform image management
- markup support for labels
- segmented buttons
- popups as a first class element
- multi-object clipboard support / inter-app data sharing
- PNG and PDF generation
The above list consumed a good part of three years of my life. In the mean time, Xamarin’s UWP support came on line as well as Tizen (still haven’t had a client ask about Tizen). Once the above list was completed and my UI code was ported, I had some great iOS and UWP apps. However, Xamirin.Forms Android apps were terrible (and still are). Launch times were / are awful and, more importantly, view rendering was/is an order of magnitude slower than Xamarin without the Forms.
AOT compiling and launch profiling mitigated the problem but, even to this day, Android performance is still terrible. Even on high end devices, Android OS would often terminate these apps because they were not responsive enough.
In addition to the above, I and my clients wanted WASM versions of our apps. There were whispers of porting Xamarin.Forms to WASM since the beginning but never and official statement. Then, in June of 2017, Frank Krueger published Ooui — Xamarin.Forms for WASM! And Frank built a masterpiece — elegant and performant. Let me be clear. Frank gave me hope for Xamarin.Forms. If it were not for Ooui, I would have dropped Xamarin.Forms and given up on cross platform development.
But, the shortcomings never went away and Xamarin’s focus was always elsewhere. Android updates continued to happen but performance just didn’t get any better. Frank quit working on Ooui (it was only a proof of concept, right?). I spent three solid months in vain trying to improve Android performance. Xamarin appeared to be more interested in Blazor than Ooui as an approach to web.
So, in the spring of 2020, I attended (virtually) Uno Conf. My number one priority: What was Uno’s Android performance. After spending hours listening to talks about build tools and toolkits, the conference was over. I had no answers and was becoming more skeptical. However, there was a virtual after-conference-social where I could meet other attendees. Once getting past the vendors, I met Carl de Billy. I shared with Carl my experience with Xamarin.Forms Android and asked if Uno would be different.
Carl was very professional but he also gave me just enough information to know where to poke. For the next week, I ran a number of experiments and was completely blown away with what I learned — without a major rewrite, Xamarin.Forms will never be capable of building performant Android apps. Why? Because the handoff between managed (C#) and native code (Java) in Android is ~10x worse than other platforms. Not a problem for Xamarin.Android apps because they use Android layout engine. However, Xamarin.Forms for Android was build to use Xamarin.Forms’ managed code for view instantiation and layout (as Xamarin.Forms does on other platforms) — which then causes 10s, 100s, 1000s, 10,000s more handoffs between managed and native. This is not so much a problem in Xamarin’s demo apps but, in more real-world listview apps, this house of cards collapses under its own weight. This is why my Android apps sucked.
In August, I started migrating my engineering analysis code base, of which 78k lines are UI code. I’m not a UWP developer, so there was a ramp up curve. 12 weeks later, a finished app, in beta test — running in WASM! When it’s out of beta, I’ll put a link here. Things I learned along the way:
- UWP debugging is disgraceful. If there had to be only one reason why UWP adoption has failed, this is it. However, Uno gives you an out by allowing you to target a number of other platforms where this isn’t an issue.
- Windows Community Toolkit is great — thank you Uno for supporting it.
- Windows.Drawing is not supported. However, Uno’s SkiaSharp support is more than sufficient to bridge this gap.
- Having very clear and tangible spec is Uno’s greatest asset. There is little doubt as to the “right way”. Unfortunately, for pragmatic reasons, Uno does have to deviate from UWP on occasion. Once you get a feeling for where those deviations are, you quickly realize that Uno is just as well architected as UWP (or probably better).
- Performance: Hands down, Uno is better. The Uno version of my Android app is jank-free!
- More work needs to be done to allow Assets to be placed once, in a shared project, and be accessible to all platform projects. For example, setting up custom fonts results in a lot of platform specific work that could be automated. I am not crazy about Xamarin’s solution to this problem and I am hoping Uno can come up with a way that, from a developer’s POV, feels just like it would if they were building a UWP app.
- There is intrinsically a lot more functionality in the still-a-work-in-progress Uno framework than in Xamarin.Forms / Xamarin.Essentials.
- Uno’s web solution is largely inspired by Ooui — which means a very lean and thin implementation.
And an unexpected finding: My UI code went from 78k lines of Xamarin.Forms code to 19k lines of Uno code! To quote Todd Wiley: “my favorite key is the [delete] key”.
To conclude: I’ve been developing Xamarin.Forms apps since mid-2015, which is almost Xamarin.Forms’s inception. Fundamentally it has two issues that are too serious and fundamental for all but the simplest apps:
- Architecture of the Xamarin.Forms Android platform
- Overly complex approaches to WASM: glomming either BlazorMobile or Uno.Wasm, rather than something more direct, like Ooui.
.NET Maui is the future of Xamarin.Forms. Unless I’ve missed something (please tell me if I have), .NET Maui does not address these fundamental issues. Without them fixed, I just can’t see where Xamarin.Forms / .NET Maui has any value over the Uno platform.