This article will expose some performance issues you might encounter when developing an Android app using Xamarin.
Typically you will encounter them if you develop your app without taking the way Xamarin works on Android into account.
First let’s take a brief look at the architecture of our Android app running with Xamarin :
Your Xamarin app is using the Mono runtime on top of the Android Runtime for all of the Android framework related classes such as Fragments, Activities and so on.
Those C# classes which inherit the Java ones are called Managed Callable Wrapper Subclasses.
This means that when you create a Fragment or a Custom View in Managed Code, the C# object will be instantiated but also the Java one and both of them will communicate through a JNI bridge.
Meaning the overhead can be quite important for both the creation of those objects but also the communication between them !
This overhead will be especially problematic when applied over large sets of objects or on performance sensitive ones such as Views.
For more information about Xamarin on Android architecture, you should read the Xamarin architecture article for Android
To give you an idea of the overhead, imagine your app needs to handle custom fonts.
One possible way of adding those fonts would be to create a View class that inherits from TextView : the FontTextView, and to define a custom attribute named “font” which will allow to specify the font in the xml layouts or in the theme/styles.
If you create this FontTextView in your C# Android Project, it will work fine but you will most likely see some performance issues.
Here are some observations on how bad it affected our app’s performances :
We had a ViewPager containing one RecyclerView per page for which each item contained 3 FontTextViews and the measured inflation time per list item view was over 8ms on a Nexus 5 !
This was especially a lot considering that more than 15 of those FontTextViews needed to be created upon arriving on our Activity, meaning the combined inflation time of them was over 120ms, which completely froze this screen’s entry animation.
At first we thought there was an issue with our implementation but even if the FontTextView contained no logic at all, the inflation time didn’t decreased.
In fact this was due to the wrappers creation time which is unavoidable when you write a class in C# which inherits a Java.Lang.Object class.
This problem was easily solved by implementing the FontTextView natively Java and creating a binding for it. Its usage in the Xamarin project was identical but it was native fast, inflation time per view was <1ms instead of 8ms !
But this means you need to have a dedicated native codebase per targeted platform plus the Xamarin codebase.
Note : The easiest way to efficiently add custom fonts to your Xamarin Android project is to create a C# Binding to the Calligraphy native android library !
When you decide to natively implement some features of your app, you will have to maintain multiple codebases : The Xamarin one, and the multiple native ones.
Here is an example of the general project structure resulting of this choice. Let’s say your app embeds a Calendar with some very specific features and rendering. As discussed before, the best way to implement that custom Calendar without any big performance penalty would be by creating a native project which will handle the rendering natively and just pass the range of dates to display in the Xamarin project.
This is what this project’s structure would look like if the MyCalendar view was implemented natively on Android and on iOS.
As you can see the project structure became more complex as it now relies on multiple codebases of different languages, frameworks and IDE’s !
Every time you want to change the MyCalendar class on Android or iOS, you will have to :
- Open your native toolset
- Modify the code
- Compile it
- Embed the compiled project in your Xamarin binding project
- Build and run your Xamarin project
Much more time consuming than just modifying an C# implemented Android Calendar View or an iOS one.
It is more complex to maintain but worth it on performance sensitive classes which are intensively used by the framework ( such as Views ).
Xamarin is an interesting solution which works well. Given the resulting app’s architecture, some extra care have to be taken especially to keep performance on par with native apps.
If you need to redefine Java or Android classes ( typically views ) that are often created or override performance sensitive method ( such as onDraw ), always prefer to write them in java and create a binding to the .jar or .aar.
It is also better to prefer native Android libraries and bind them over their Xamarin C# port for performance reason but also because they are often better maintained.
As a general rule you should threat Xamarin as a sort of supervisor which injects all of your data and business logic in the framework your are targeting and prefer native implementations of performance sensitive classes.
By Yannick Gerard, Android Developer