Pagination With Observablecollection with Xamarin on iOS and Android

Your users expect your apps to perform their best. Lists are an important part of any apps, however they are sometimes misused and the #1 source of lags in applications. As a reminder, any long running operation executed on the MainThread will block and will be perceived by your users as Freezing or lagging.

Both iOS and Android provide mechanisms to ensure the upmost performance of those UI. Android provides the RecyclerView and iOS provides a UITableViewSource. How to leverage those controls is extensively discussed on the web and is beyond the scope of this article.

Let’s say you need to handle very long lists (ex: hundreds of items). The first rule of thumb is that you do not want to load all the items at once. Even if done on a background thread, the user will perceive your application as slow since thousands of records need to be downloaded over a possibly poor network. Meet pagination.

If you have been using MVVM on .net, you must be familiar with ObservableCollection. This a collection class that dispatches INotifyPropertyChanged events in relation to Collections.

Let’s see how we can leverage ObservableCollection for pagination:

public class LazyObservableCollection : MvxObservableCollection<CellViewModelBase>, ILazyObservableCollection
    {
        //Delegate that returns the list of cells as well as the total number of items available on the API
        public delegate Task<Tuple<IEnumerable<MvxViewModel>, int>> PageLoaderDelegate(int currentPage);

        private readonly PageLoaderDelegate _pageLoader;
        private int _totalNumberOfItems;
        private int _currentIndex;
        private MvxNotifyTask _executingTask;

        public LazyObservableCollection(PageLoaderDelegate pageLoader, int pageSize) : base()
        {
            _pageLoader = pageLoader;
            _pageSize = pageSize;
            _currentIndex = 0;
        }

        public Task LoadMoreAsync()
        {
            if (_executingTask?.IsSuccessfullyCompleted ?? true) {
                int currentPage = _currentIndex / _pageSize;
                _executingTask = Task.Run(() => _pageLoader(currentPage).ContinueWith(t => {
                    var cells = t.Result.Item1;
                    var totalNumberOfResults = t.Result.Item2;
                    _totalNumberOfItems = totalNumberOfResults;
                    _currentIndex += cells.Count();
                    AddRange(cells);
                }, TaskScheduler.FromCurrentSynchronizationContext()));
            }

            return _executingTask;
        }

        public bool HasMoreItems => _currentIndex < _totalNumberOfItems;
    }

    public interface ILazyObservableCollection
    {
        Task LoadMoreAsync();
    }

The example above has been simplified for the purpose of this post. Some improvements include the ability to add a Loading cell when items are being loaded and Exception handling.

There are 3 important pieces in this snippet:

public delegate Task<Tuple<IEnumerable<MvxViewModel>, int>> PageLoaderDelegate(int currentPage);

This is the delegate that tells the observable collection how to get the next round of paginated view model that it needs to display.

LoadMoreAsync

LoadMoreAsync is where the magic happens. We check if there is a Loading task already running and if there isn’t we create a new Task to GET the next round of items. Finally we make sure to update the Collection from the UIThread to prevent updating the UI from a background thread.

ILazyObservableCollection

This is the interface that abstracts aways the functioning of the observable collection. on iOS you would call collection.LoadMoreAsync() from the UITableViewSource in GetOrCreateCellFor when you detect that the current cell index is at the end of what has already been loaded. On Android this would be invoked from onBindViewHolder.

Happy coding!

MvxMessenger and Subscription Hell

MessengerBus allows your application to subscribe and publish events form different parts of your application while giving you the flexibility of a loosely coupled architecture.

MvvmCross provides its own built in Event aggregation Messenger: MvxMessenger with the twist that it is implemented using WeakReferences. (I talked more about WeakReferences in my Post about Memory and Performance.) In short, WeakReferences helps in preventing Strong object references thus reducing memory leaks; making it the best contender tool of its kinds for mobile apps.

MvxMessenger is easy to integrate in your application, however its use is intricate and often leads users to bugs that they are not expecting.

“My View is no longer visible on screen but I keep getting subscription notifications in my ViewModel”

This is a recurring question I get from developers. First, If you read my blog post about avoiding memory performance issues with Xamarin, this shouldn’t be happening to you. One of the beauties of the MvvmCross framework is that fact that it promises all the viewlifecycle calls to your ViewModel, this you should be using the `ViewWillAppear` and `ViewWillDisappear` respectively to subscribe and unsubscribe events.

You may ask, “MvvmCross uses WeakReferences, why am is my ViewModel still receiving notifications even when the View is disposed?“

If this question popped up in your mind, good job! In fact, iOS or and Android will usually dispose views when it is no longer part of the View hierarchy or Navigation Stack as long as there are no strong references preventing the OS from doing so.

Trick: Since all Native objects implements the IDisposable Interface in Xamarin, a trick I have used throughout the years to is to override the Dispose() method and log that the view is effectively being disposed. This allows you to know when a View is retained in memory by just looking at your console logs while debugging.

However, the View being disposed does not guarantee that its associated ViewModel is also disposed. iOS has its own Garbage collection strategy, on top of that Xamarin has its own algorithms to determine when objects should be disposed as part of its runtime. That said, you ViewModel may still be in memory while it is scheduled to be disposed.

The #1 rule that will prevent your form a lot of headaches is to Always make sure your subscription tokens are disposed when you no longer need them.

Happy coding!

How to prevent Memory and Performance pitfalls on xamarin

Mobile devices have restricted resources compared to desktop or servers: smaller CPU, lower RAM, limited connectivity... Today, I wanted to address concerns about memory management on mobile devices. I get asked a lot by questions from junior and seasoned developers alike, about OOM (out of memory) exceptions, memory leaks and slow downs.

Out of memory exceptions occur when your app needs to allocate more object but the Heap is full. Memory leaks occur when objects are allocated in memory but the Garbage collector (GC) is not able to collect these objects because some live objects hold references to them. Finally slow downs (or lagging) can occur when the Heap is full and the Garbage collector incessantly tries to free up memory which can hog the UI thread.

Today I wanted to share some best practices that I leaned throughout the years developing mobile applications.

1. Reduce file sizes

This is the most common way of getting yourself quickly out of memory. Let’s say you have a splash screen that uses very high res images, (over 100s of megabytes) and additionally you open these giant PDF files in memory and you have these screen rendering tons of images that are also very high res. Soon enough you will end up with no memory left for you to allocate objects that support to business logic and you get OOM exceptions. I recommend checking the size of the files that you load in memory, and if you need to open large files, make sure that those are disposed when you don’t need them anymore.

2. Avoid cyclic references

I am not going in detail about explaining weak references. There are a tons of good resources on the web. iOS uses ARC to count the number of references to a given object in order to know if that objects can be collected. Additionally, Xamarin provides Garbage collector, that live on top of ARC that also free up objects when these are not strongly referenced by other objects. Freeing references to objects can become overwhelming and hard to do in the long run. Thankfully, .Net exposes the type WeakReference that allows you to reference objects in a “Weak“ manner. Thus, objects referenced can still get collected.

3. Unhook your event handlers

EventHandlers can prevent objects from getting garbage collected.

Button.TouchUpInside += (s, e) => {
  this.ShowAlert("...");
}

In the code above, because “this” is referenced in the lambda, it will be hold in memory. Additionally if Button is referenced by This, you get a cyclic reference which means either object will never get collected resulting in a memory leak.

To prevent this, start by always using a method vs lambda expressions and if you really need/want to use lambdas then use WeakReferences for instance objects within it.

Button.TouchUpInside += DoHandleButtonTouch;
Button.TouchUpInside -= DoHandleButtonTouch; 

private void DoHandlerEvent(Object sender, EventArgs e)
{
//dosomething
}

A good pattern that I have applied throughout the years is to hookup events in ViewDidAppear (OnCreate for Android) and unhook these event in ViewWillDisapear (OnDestroy).

If you have additional best practices, please free to share in the comments :)

Happy coding :)

Sharing Views With MvvmCross

MvvmCross uses IMvxViewsContainer to determine which ViewController it needs to initialize. The IMvxViewsContainer implementation uses both Convention OR the Generic argument TViewModel of MvxViewController<TViewModel> to determine the mapping TViewModel <=> ViewController.

Problem comes when you have very similar ViewModels with slightly different behavior but identical UIs. With the built in IMvxViewsContainer implementation, you end-up having to create duplicate Views on the Platform side that each map to its own ViewModel.

To change that behavior, you can add additional mappings to IMvxViewsContainer by overriding the Setup class on the platform. For iOS, this may look like this:

    protected override void InitializeViewLookup()
        {
            base.InitializeViewLookup();
            var viewModelViewLookup = new Dictionary<Type, Type>{
                { typeof(FirstChildViewModel), typeof(CommonChildViewController) },
                { typeof(SecondChildViewModel), typeof(CommonChildViewController) },
            };

            var container = Mvx.IoCProvider.Resolve<IMvxViewsContainer>();
            container.AddAll(viewModelViewLookup);
        }

Next time you request FirstChildViewModel or SecondChildViewModel, IMvxViewsContainer will return a new instance of CommonChildViewController, this way you don’t end up with duplicated views.

Happy coding!

UIPickerView and MvvmCross

Mvvmcross is an open source cross platform mobile framework enabling Xamarin developers to maximize code reuse and, as stated in the name, allow using the Mvvm software architectural pattern to bind behavior directly to platform controls.

Recently, I have had to implement an UIPickerView and attach it to a UITextField as an InputView. MvvmCross is rich with custom controls and luckily and I was pleased to find that someone already thought about providing a ready to go implementation: MvxPickerView.

We will create a NamesViewModel and NamesViewController with one UITextField

In your ViewController, the code to create the Picker looks like this:

public override ViewDidLoad()
{
  var picker = new UIPickerView();
  var pickerViewModel = new MvxPickerViewModel(picker);
  picker.Model = pickerViewModel;
  picker.ShowSelectionIndicator = true;PickerTextField.InputView = picker;
}

In your NamesViewModel add the following Binding properties:

private string _selectedName;
public string SelectedName 
{
  get { return _selectedName; }
  set {SetProperty(ref _selectedName, value);}
}
private ObservableCollection<string> _namesCollection { get; set; }
public virtual ObservableCollection<string> NamesCollection 
{
  get { return _namesCollection; }
  set { SetProperty(ref _namesCollection, value); }
}

The we need to initialize the collection and feed it some values to be displayed by the picker:

public override Task Initialize()
{
    NamesCollection = new ObservableCollection() {"Karim", "John", "Peter"};
}

Back in your ViewController, we need to set the bindings so that the pickerModel knows where to source the data that it needs to display:

protected override void ViewDidLoad()
{
  base.ViewDidLoad();
  var picker = new UIPickerView();
  var pickerViewModel = new MvxPickerViewModel(picker);
  picker.Model = pickerViewModel;
  picker.ShowSelectionIndicator = true;
  PickerTextField.InputView = picker;

  //create the bindings
  this.CreateBinding(PickerTextField).To((NamesViewModel vm) => vm.SelectedName).Apply();
  this.CreateBinding(_pickerViewModel).For(p => p.ItemsSource).To((NamesViewModel vm) => vm.NamesCollection).Apply();
  this.CreateBinding(_pickerViewModel).For(p => p.SelectedItem).To((NamesViewModel vm) => vm.SelectedName).Apply();
}

And that’s it, you should be able to see the the pickerView bound to the collection of names that you have set in your ViewModel.

Happy coding!