CollectionViews are an excellent tool for presenting ordered sets of data that require a flexible layout. I recently used CollectionViews to create a “Presentation Generator” enhancement for an enterprise tablet app.
The tool needed to be completely dynamic: allowing users to add, delete, edit, and rearrange slides. Each slide was represented by a separate CollectionViewCell which held a static image of the slide.
I noticed that as the number of slides in the presentation grew, the collection view began to perform poorly. Scrolling the collection view became slow and unresponsive, and the app would crash after extended use.
Why was this happening?
CollectionViews in Xamarin.iOS have a GetCell method, which is the same as the cellForItemAtIndexPath method in Objective-C. Calling CollectionView.ReloadData(), causes this method execute. When scrolling, as cells slide on and off the screen, the reusable cells are dequeued in the GetCell method. This means that the GetCell method is invoked repeatedly. The following line in the GetCell method was causing the problems:
myCollectionViewCell.Image = UIImage.FromFile(ImagePath);
The issue was that every time the collection view needed to reload its data, the GetCell method would execute and the image for each of the cells would be loaded. Loading the same image over and over was leading to poor performance.
The Solution:
To solve this issue, instead of loading the images in the GetCell method, a List<UIImage>images was created with the images preloaded. Now, instead of doing this:
myCollectionViewCell.Image = UIImage.FromFile(ImagePath);
We could do this:
myCollectionViewCell.Image = images[indexPath.Item];
There was significant improvement in scrolling performance. Memory warnings and crashes stopped.
Another thing to note here is the usage of UIImage.FromFile(), which lazy-loads images asynchronously, so it is better suited for situations where several images need to be loaded at one time. UIImage.FromBundle() automatically caches an image after its loaded, making it ideal for situations where the same image needs to be loaded repeatedly.