First impressions of Xamarin.Forms
This post is backed up from my old blog and was posted at 2014-06-14.
With the release of Xamarin 3, they released a new library called Xamarin.Forms. It’s a library for building cross-plattform shared UI. This means you write your UI once and the controls will be mapped to native controls. With it you can write your UI once and share it across Windows Phone, iOS and Android.
Xamarin also started a contest for writing a first app with Xamarin.Forms. With this blog post, I want to submit my little app.
Currency Converter
My app is a little Currency Converter. It is hosted on GitHub, feel free to check it out! The app itself isn’t very spectacular, it’s more a tech demo for the underlying technology and just a little part of a big picture. More on that later.
At first some numbers determined by Visual Studio Code Metrics.
- Lines of Code (all): 1423
- Lines of Code (WP): 1050
- Lines of Code (iOS): 997
- Lines of Code (Android): 982
- Percentage of shared code across all platforms: ~ 80%
Currently I’m sharing about 80% of code, which means that 20% are platform dependent. I think this is currently good, but can be done better. I’m currently looking forward to share more than 90% of code.
At this time, the project contains a lot of platform dependent services, like getting network information, access to local storage, read file from app package or provide access to phone information. Since this is done now, more and more platform independent code will be written in order to complete the big picture of my tech demo app. But, what exactly is the big picture?
The big picture
In order to understand the big picture, I’ll need you to show the project structure:
[Picture not available anymore, sorry!]
Let’s start from the root to the inner elements.
The root contains two folders: Apps and Shared Code Base.
The Apps folder contains three projects: One for each platform: An Android app (currently targeting Android API 17 (4.2)), an iOS universal app (targeting iOS 7) and a Windows Phone app (targeting Windows Phone 8.1). This code is, of course, platform dependent.
The other, more interesting, part is the solution folder Shared Code Base, which has 4 parts.
The Core folder contains platform independent mobile contracts and services. It’s not only platform independent, it is application independent too. This means, that the core project contains generic services, which could be used in different apps. Those services are (e.g.) caches, network information, analytics or configurations.
Since some of the core functionality is platform dependent, we need the implementation for each platform. Here comes the folder Platform Implementations in place. It contains implementations for some services (e.g. network information, access to local storage and so on), but still: Those project are app independent and can be used for more apps. This is why the code is contained in Shared Code Base. To be honest, it should be splitted into app (in)dependent and shared code, but that’s a kind of micro management and currently not suitable for this little tech demo.
Until now, we only have app independent projects. To develop the app itself, we need the next part of the Shared Code Base: The Currency Converter folder. It contains platform independent code for the functionality of the app. In this case: Some services to get currency information from the European Central Bank or access to the flag names to have some nice images for each currency. Since this is platform independent it can be used not only for apps but also other projects like desktop apps or even websites (or this could work we will see later).
The last part is the Views folder. It contains ViewModels and Views. According to the MVVM-pattern the ViewModels contain all the logic a view can do. The Views project itself contains the views or pages for each platform.
But wait? We talked about a lot of architecture now, but where exactly is Xamarin? For my demo I wanted to introduce Xamarin as late as possible. Xamarin is only available for the Apps, **Platform Implementations **and the Views project (not the solution folder! The ViewModels project does not reference Xamarin).
Why is Xamarin introduced so late (which means I can’t use it for services using their DependencyService)? On one side, it is to be more independent. Remember when I said you could use it for websites or desktop apps? In this cases you probably don’t want a dependency to Xamarin, since it is not needed. Or imagine a scenario where you as a company provide some services (like the mobile core and currency converter) but you outsource the development of the app UIs. This way, you can share all your business logic and the company, which develops the UIs, just consume your services.
On the other side: Everything is interfaced and loose coupled. I use the excellent Autofac IoC for gluing everything together. Take a look here and here for the gluing.
The app itself
Let’s come from an architecture overview back to the app itself. Let me show you some screenshots at first (for more head over to the GitHub repository):
Windows Phone
iOS
Android
Yep, the app itself won’t win a beauty contest (I’m a terrible designer). So, what does the app currently do? Converting currencies! That’s all? Yes! Really! It is much more interesting whats under the hood. So I want to dive into the code now and show some features the underlying Mobile (and it’s necessary platform implementations) provides to the user. I’ll link the classes to GitHub, so you have the implementation at your fingertips (for some platform implementation I will just link the Windows Phone implementation, since I’m familiar with that platform and very little feature are currently not tested with the other platforms).
Caching
Currently 3 types of caches are support: An in-memory-cache, a file-cache and a navigation cache. The in-memory-cache is a app lifetime cache and will be deleted when the app is restarted. The file-cache will survive app restarts, since it will cache everything to files immediately. Those two caches can be swapped vice-versa. To be honest: The file cache is currently tested for WP only. I implemented it for iOS and Android, too, but haven’t tested it yet.
The navigation cache is a special cache for the ViewModels when they request a change to another page. Since Xamarin.Forms does not provide a NavigationParameter or somethin we need to build something. This cache should not be swapped for one of the other caches.
Configuration
The Mobile project contains an interface IMobileConfiguration and an IMobileConfigurationProvider. Imagine a scenario here as the one before: You provide a library which has some settings. It will use the IMobileConfiguration interface to determine those settings. The current implementation of IMobileConfigurationProvider reads a MobileConfiguration.json file, where the settings are set.
Lifecycle Management
All three apps override their “Application” class to provide access to their application lifecycle events (WP, iOS, Android). This is currently used for the analytics part.
Networking
On every platform we have the ability to get the current network state and provide an event handler, when it changes (WP, iOS, Android).
Platform information Provider
For the analytics part we need a platform information provider to get access to the current platform’s user agent or screen size. The implementation is currently very simple and does not provide information about the model or manufactures of the mobile phone (WP, iOS, Android).
Analytics
This is a part, I really love: Mobile phone analytics using Google Analytics to get a real time usage statistic of your app:
[Picture not available anymore, sorry!]
Pure awesomeness! How does it work? I grabbed the GoogleAnalyticsSDK for Windows Phone from CodePlex (thanks to Tim Greenfield for this, I hope I can contribute this back to the library). I built this library against Xamarin.iOS and Xamarin.Android to use it platform independent. After that it just takes one line of code to track something:
_viewModel.AnalyticsService.TrackView("MainPage");
// or for the app lifecycle events
_applicationLifecycle.OnAppResuming += () =>
{
if (DateTime.Now.Subtract(_suspendTime) > TimeSpan.FromMinutes(_configuration.SessionTimeout))
{
StartSession();
}
TrackCustomEvent("ApplicationLifecycle", "Resuming", String.Empty);
};
_applicationLifecycle.OnAppSuspending += () =>
{
TrackCustomEvent("ApplicationLifecycle", "Suspending", String.Empty);
_suspendTime = DateTime.Now;
};
For me, having analytics in an app is very important to get an understand of how your users are using the app.
Xamarin.Forms
With Xamarin.Forms it is really easy to write shared UIs. Take a look at the MainPage or the CurrencyListPage. It is only defined on time and mapps to native components. Really cool! It is really easy too to mix shared UI code with native code. Take a look at ApplicationBar from Windows Phone. Unfortunately I didn’t implement a custom renderer yet.
Thanks to the Binding system Xamarin.Forms provide you just need to implement INotifyPropertyChanged within your ViewModels to get a OneWay or TwoWay-Binding, which makes it very easy to update your UI and ViewModels (and vice-versa).
Impressions of Xamarin.Forms
Although this post didn’t contain really much about Xamarin and Xamarin.Forms, it is really a pleasure to develop apps with it. The set up of the build environment (including a MacMini to compile iOS) is super easy and works fantastic. My development process is currently to write the feature for Windows Phone at first and then port it to Android and iOS. I’m using Visual Studio for development, so I have everything I need at my fingertips. You get the whole experience you are used to across three platforms. Although debugging on Android Simulator is horrible slow (due to extrem slow Android emulators), it works really nice!