Software development

Xamarin Forms: Seriously

Topics
xamarin, .net, xamarin forms, Software development, Android, iOS, windowsphone

Cross platform dev is expensive, time consuming, and all you're doing is saying the same thing twice, or even thrice. What a waste of effort, right? Isn't the whole point of programming to spend effort efficiently? Lucky for us, somebody else has already done the hard work, and created Xamarin Forms.

For the uninitiated, Xamarin Forms is a cross-platform framework that allows you to share both UI code and business logic across platforms. It targets Android, iOS, Windows Phone 8.1 RT, Univeral Windows Platform and, soon, MacOS. It sits on top of "regular" Xamarin which provides C# bindings to the Android and iOS SDKs, and allows you write cross-platform business logic, but requires platform-specific UI code.

I'd been interested in Xamarin Forms for a while, so when I had an opportunity to write a brand new app, I jumped at the chance.

The Job

The project in question was a small (about 7 or 8 screens, no extensive animation of theming) mobile app. Our goal was to hit Android, iOS and WP8, and we had a deadline of around 5 months. The development team consisted of myself and the esteemed Mikko Toivanen. We both had extensive experience in Windows development, especially around the 'XAML-y' frameworks, which made picking up Xamarin Forms very easy. As such, we decided to do all our UI in XAML and lean heavily on an MVVM architecture and Xamarin Forms' binding framework.

The Result

We came in on time and under budget. Both Mikko and I agreed that working with the framework itself was surprisingly pleasant, and we would definitely do so again, given the opportunity.

(In fact, we found it so pleasant, that we decided to take out all of the useful stuff, and make a starter project template out of it. Check out Xalami if you're thinking about starting a Xamarin Forms project of your own!)

After tallying it up, we came out to a whopping 85% code shared between platforms--and that's a fairly conservative estimate. If you only count code we actually wrote (i.e. ignore the boilerplate template code), it probably comes closer to 90% or so.

That's the short version of the story. I had a lot of fun working this project, and it definitely paid off for us. But I can't spend the whole post gushing, so why don't we start by talking about...

The Rough Stuff

That is, the parts that didn't work, the parts that frustrated us, the parts that spiked our WTFs / min through the roof...all that.

Brittle Build Blues

This one is a little harder to quantity, because I can't point to just one or two things and say There. That's the issue right there. But both Mikko and I felt that we spent a lot of time fighting the build system, and that when it did break, it often broke in surprising ways, or gave misleading or unhelpful error messages.

One particularly egregious example that ate up about an hour of my time happened when I accidentally imported a type from the Windows.UI.Xaml namespace in the PCL project. This resulted in the Windows platform DLL being included in the PCL build, which wrought all sorts of havoc. I was confronted with 1800 errors, and only told something about a duplicate .winmd. I ended up having to do some Git forensics to figure out where I broke the build, and finally isolate the one line that did it: using Windows.UI.Xaml buried in one of my IValueConverters.

Windows Phone Support

Windows Phone 8.1 support was one of the customer's requirements. Unfortunately, reflecting its lack of broader market share, WP8's support in Xamarin Forms is spotty at best. We ran into a few problems that sucked up a fairly dispropotionate amount of developer time.

Font Styles

Xamarin Forms comes with 6 font styles out of the box, which it calls Device Styles. They are styles for:

  • Body text
  • Caption text
  • List Item text
  • List Item detail text
  • Subtitle text
  • and Title text.

Unfortunately, the only styles that worked on WP8 were the Title Style and the Subtitle Style. All the others rendered at unreadably-small 10-point text or so. It was pretty bad.

Device styles
Wacky, huh?

Figuring out a.) that it was a platform bug and not our fault and b.) how to work around it in a manner that didn't result in massive headaches later, ate up nearly a week around the beginning of the project. We submitted a bug report and a PR with a partial fix that ultimately resulted in a real fix that should be in Xamarin Forms 2.3.5, so this story ultimately has a happy ending. Hooray!

.resx File Issues

We ran into the same issue described in this MSDN blog post--namely, trying to access application resources that live in a Portable Class Library (henceforth PCL) from a WinRT context, you get a MissingManifestResourceException. Tracking this one down was an interesting rabbit hole of debugging, and we're lucky we noticed it at all--we only experienced it in Release, on a physical device. This could have very easily been a bug that snuck up on us after releasing to the store, resulting in much wailing and gnashing of teeth.

We ended up using solution #2 from the above blog post--some truly dirty runtime Reflection-based hacking where we sneak into our .resx file's generated class, and replace its .NET ResourceManager with a WinRT ResourceLoader. Easily one of the dirtiest hacks I've ever had to employ in a shipping product.

In fairness, this one isn't totally Xamarin's fault--it's more a consequence of trying to use PCL .resx resources from WinRT, but it's still a hurdle that we likely wouldn't have had in a platform-native project.

The Good Stuff

Whew! Now that that's out of the way, let's get to the fun parts. I said at the beginning that both Mikko and I agreed that the platform was pleasant, so let's justify that!

You Already Know This

Since Xamarin Forms is a XAML-based framework, virtually all of our WPF/Silverlight/WinRT knowledge was able to transfer over. There were some stumbling blocks as we learned the quirks and idiosyncrasies of a new flavor of XAML, but for the most part it just worked how we expected. As an added bonus, any .NET libraries that worked in PCLs worked just fine here, too. JSON.NET, MVVM Light, Akavache and Reactive Extensions were all welcome companions on this project.

If you've got any previous experience in a recent .NET ecosystem, a lot of that knowledge is going to carry right over.

Binding and MVVM

I've used Java Swing and Windows Forms, and those two frameworks were enough to convince me that manual UI twiddling in code is for the birds. Since being introduced to binding-and-markup-based frameworks, as Xamarin Forms' XAML is, I've come to enjoy the way it encourages good design, and handles the messy stateful UI management for you.

Custom Markup Extensions

If you've spent time in Silverlight or WPF development, you're probably nodding your head right now. If not, a quick demonstration is in order.

<!--Extraneous stuff removed.-->
<ContentPage xmlns:ext="clr-namespace:ProjectName.Extensions">
    <Label x:Name="LoginLabel" Text="{ext:TranslateExtension LandingPage_Login}"/>
</ContentPage>

Here, we have a class named TranslateExtension that lives in the ProjectName.Extensions namespace that implements the IMarkupExtension interface. The interface defines a single ProvideValue method that returns an object. In the case of our little TranslateExtension here, it does the work of going and looking up a localized string, and returning it. This allows a super concise form of localizing resources in XAML.

This is much nicer than the more common song-and-dance in WinRT-land of {Binding Source={StaticResource SomeResxGeneratedClass}, Path=SomeVariableName}.

We also had an ImageExtension which returned an ImageSource appropriately scaled for the platform and screen size, just by referring to the filename. Way easier than any alternative I could think of.

<!--Like so.-->
<Image x:Name="Chevron" Source="{ext:ImageExtension chevron_white.png}"/>

It Worked

I know this might seem obvious, but it was a little hard to swallow the pitch: I can write an entire cross-platform application with shared code? Nah, no way.

But the truth is, we came out with the majority of our code being shared between platforms, and neither of us had to learn much more Android or iOS or Windows than we already knew. Development was easy, the apps ran well, looked native and were easy to maintain.

The Verdict

You'll probably fight your tools a little bit (and when don't you?), and probably have days where your WTFs per minute approach critical mass. But at the end of the day, you get to write your application once, in a feature-rich, modern language and, like magic, deploy it on more platforms than you can shake a stick at.

Thumbs-up, would use again.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.