App Development

How to get the most out of Xamarin binding libraries

Stoplight pattern

Whether you are a veteran Xamarin developer or just getting started, there will come a time when you will want to use some cool library, framework, or SDK that is only available in Objective-C or Java.

For example, you might want to integrate with a third party library in order to hook into another platform like Facebook or Uber. Perhaps you want to use a popular image loading library that only exists natively for Android or iOS. You don’t want you and your development team to have to reinvent the wheel, so leveraging tools that others have created is a good way to save time and money in your development process. Fortunately, Xamarin offers a means to accomplish this through a binding library.

divider 600

What is a binding library?

A binding library is a wrapper around a native library which allows the developer to consume a Java or Objective-C library or framework as if it were written in C#. The binding library, when generated against a Java library, does not always work the way we would expect a C# API to work. For instance, it may use a design pattern that is common to Java but does not fit in a C# project.

Async-Await

This is especially true for libraries which expose async operations. Where in Java we might take a callback or return a Future, C# typically prefers to deal with Tasks to support the Async-Await language feature introduced in .NET 4.5. Providing proper support for Async-Await to the consumers of your binding library is essential to maintaining a clean, easily maintainable codebase.

The Native Side

Our Java API was designed with functional callbacks, so a query operation would look something like this:

public interface ThingService {
	void getThing(long id, Callback<Thing> callback);
}

public interface Callback<T> {
	void onSuccess(T data);
	Void onFailure(Throwable error);
}

Consuming that API might look something like this:

ThingService service = … // instantiate an implementation
service.getThing(512L, new Callback<>() {
	@Override
	void onSuccess(Thing data) {
		// handle success
	}

	@Override
	void onFailure(Throwable error) {
		// handle error
	}
});

There are other patterns in Java for exposing asynchronous methods such as the use of Future. In this pattern, the API exposes methods which, instead of taking a Callback<T> type, return a Future<T> type that represents an ongoing operation that will complete at some point in the future with an error or a result.

Similar to Futures, .NET 4.5 introduced the Task class. A C# Task is very similar to a Future, except their usage is made much simpler with language-level support via the async and await keywords. When an API returns a Task instance, the caller can await the Task and suspend execution until a result is available or an error is thrown. This allows the programmer to chain asynchronous operations as if they were synchronous, while avoiding Callback Hell. The compiler does the heavy lifting under the hood to wrap and unwrap Task by delegating background execution to a common threadpool.

Our previous API in C# would ideally look like this:

public interface ThingService {
	Task<Thing> GetThing(long id);
}

Consuming that API might look something like this:

var service = … // instantiate an implementation
var thing = await service.GetThing(512L);
// do something with thing

But the C# API generated by the Xamarin bindings produces a method with an interface callback:

public interface ThingService {
	void GetThing(long id, ICallback callback);
}

Introducing Additions

While this API is functional, we can be good citizens and make life easier for our C# friends by providing convenience methods which return Task. When creating a Xamarin binding project, we can optionally create partial classes (with matching names + namespaces) within the Additions folder with custom methods which will be merged into the generated class at compile time. Async-Await and Library Bindings folders An example partial class for our generated ThingService might look something like this:

namespace Example
{
    public partial class ThingService
    {
        public Task<Thing> GetThing(long id)
        {
            var tcs = new TaskCompletionSource<Thing>();
            GetThing(id, new ThingCompletion(tcs));
            return tcs.Task;
        }

        private class ThingCompletion : Java.Lang.Object, IThingCallback
        {
            private readonly TaskCompletionSource<Thing> _tcs;

            public ThingCompletion(TaskCompletionSource<Thing> tcs)
            {
                _tcs = tcs;
            }

            public void OnSuccess(Thing thing)
            {
                _tcs.SetResult(thing);
            }

            public void OnFailure(Throwable t)
            {
                _tcs.SetException(t);
            }
        }
    }
}

The implementation of these convenience methods calls the callback method internally and wraps its result (or error) in a Task using a TaskCompletionSource. It’s important to note that calling SetException on the TaskCompletionSource will cause that exception to be thrown when the Task is awaited by the consumer, so in this example the caller should catch and handle those exceptions:

var service = … // instantiate an implementation
try 
{
	var thing = await service.GetThing(512L);
	// do something with thing
}
catch(ApiException e)
{
	// handle error
}

It’s easy to see how one might expand on this simple example to create a much better API for Xamarin apps consuming your Java library.

Quickstart-Guide-to-Kotlin-Multiplatform

A Quick Start Guide to Kotlin Multiplatform

Kotlin Multiplatform, though still experimental, is a great up-and-coming solution...

Read the article