Xamarin is a hot platform these days for writing cross-platform mobile applications in iOS, Android, and other platforms. You code in C# for all these platforms, which is great for us since we love C# and we can share code with our .NET desktop application, inFlow Inventory. We were evaluating Xamarin, so I started working on a sample application to try it out and look for an architecture which would let us share code cleanly. This post shares some of my experiences, thoughts, opinions, and code. The code is available here on github (please pardon the rough edges, it’s a prototype!).
The first big choice you make with Xamarin is do you want to build separate native UIs for each platform, or use Xamarin Forms to build one UI for all platforms. I found that the general sentiment is that Xamarin Forms can save you some effort if you’re planning on a very simple UI without too much customization for each platform, but for a more complex UI it’s better to build a separate UI for each platform. Since control over the UI/UX is important to our company, I chose the native UI route.
Given this choice, Xamarin lets you write pretty much any C# code, which means there’s no official framework for maximizing code-sharing across platforms. I’m a fan of the MVVM (Model-View-ViewModel) pattern, as I find it makes UI code easier to share and understand. I’m also a fan of Reactive Extensions, as I find that makes event-driven code much easier to work with (although there’s a substantial learning curve, since you have to learn to think in a new way). So I started by looking at ReactiveUI as a main framework, but quickly got frustrated by the scarcity of documentation and examples (or found that many of these were out of date) and the problems that I ran into.
I then looked into the MvvmCross framework, which seems to be used more heavily in the Xamarin community, and this generally worked pretty well. This provided a nice structure where I could set up ViewModels and data-bind them to the platform-specific interface code. For example, the shared ViewModel would have a property storing the value of a search query, as well as the logic of actually performing the search, and the platform-specific code would create the search UI control, and have some bindings so that when the user typed in a search query, that it be reflected in the ViewModel. Some other concepts like working with tables have special handling in iOS and Android, but these are pretty similar and straightforward to implement. Surprisingly, the logic for navigating between different screens can be handled in the shared code (by navigating to a ViewModel in the shared code, then each platform finding the view corresponding to that ViewModel).
I actually also ended up using pieces of ReactiveUI in a more limited capacity; this let me write the event-based code in a nice, reactive way, while using MvvmCross’s more mature data-bindings and navigation frameworks.
I did this prototyping on Windows using Visual Studio. Initially I tested it mostly on the Android platform, using the Xamarin Android Player simulator. This toolset works quite well, you can just hit Debug in Visual Studio and it updates the Android simulator and breakpoints work as you would expect. When working on the iOS platform, unfortunately Apple only allows compiling and testing iOS apps using a Mac, but Xamarin has come up with a way to use another Mac machine on the LAN as a build-server, so that you can hit Debug from Visual Studio, and it will run your program on the iOS simulator running on the Mac. My experience was that I felt it worked better than I expected, but was significantly buggier than the Android tools. For example, the debugger often wouldn’t work, and I ran into some problems with the iOS UI editors. You can also run the Xamarin Studio IDE directly on a Mac, which from a very brief trial was better than I expected, but not as good as Visual Studio.
Incidentally, iOS has a concept (supported in Xamarin) called storyboards that allows you to design multiple screens in one file, as well as the navigation and transitions between them (“segues”). I chose to have each storyboard only contain one view, for two reasons. First, I heard that when working with large storyboards in a team environment, source control merge conflicts can be a huge pain. Secondly, since Android doesn’t have a similar concept, having a one-to-one mapping of storyboards and views allowed me to keep the same paradigm across both platforms, thus sharing more code.
I also prototyped using local storage for the mobile apps in the form of a local SQLite database. The open source packages for SQLite worked flawlessly for me across both platforms, with only minimal platform-specific initialization code, and having shared code for dealing with a local SQL database was a big win.
As one indication of how well the code-sharing with Xamarin and this architecture works, when I updated the Android prototype to add the ability to sync with a copy of our desktop application, the same functionality worked immediately on iOS with no code changes at all required; all the changes took place in shared code and just-worked. (This syncing code was a dirty hack that I’m too embarrassed to share, however.)
Overall, I was very impressed with Xamarin; although I ran into some bugginess, it’s very impressive what they’ve pulled off. I think it’s probably the best way to develop mobile apps that need to target both Android and iOS today. The community has a lot of momentum behind it and is continuing to grow, with some help from Microsoft. It’s a lot of fun to be able to share C# code between desktop, Android, and iOS, and see changes from my physical phone propagate to my desktop.
I’ve mostly talked about this in feelings and generalities, but the code is available here, and I’d be happy to discuss specifics in the comments!
Interested in working with Xamarin? We’re hiring! You don’t necessarily need Xamarin experience already, but if you’re an expert, I’d love to hear all the things I did wrong!